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.
162 lines
4.6 KiB
162 lines
4.6 KiB
from abc import abstractmethod
|
|
|
|
from django.conf import settings
|
|
from django.contrib.auth.base_user import BaseUserManager
|
|
from django.urls import reverse_lazy
|
|
from django.utils.translation import ugettext_lazy as _
|
|
from django.db import models
|
|
|
|
from mptt import (
|
|
models as mptt_models,
|
|
managers as mptt_managers,
|
|
)
|
|
|
|
# Create your models here.
|
|
STATUS_NEW = 0
|
|
STATUS_ACTIVE = 25
|
|
STATUS_DELETED = 50
|
|
|
|
STATUS_DEFAULT = STATUS_NEW
|
|
|
|
STATUS_CHOICES = (
|
|
(STATUS_NEW, _('Новый')),
|
|
(STATUS_ACTIVE, _('Активный')),
|
|
(STATUS_DELETED, _('Удаленный')),
|
|
)
|
|
|
|
|
|
class CaseInsensitiveQuerySet(models.QuerySet):
|
|
CASE_INSENSITIVE_FIELDS = ('email',)
|
|
|
|
def _filter_or_exclude(self, negate, *args, **kwargs):
|
|
for field in self.CASE_INSENSITIVE_FIELDS:
|
|
if field in kwargs:
|
|
kwargs[field + '__iexact'] = kwargs[field]
|
|
del kwargs[field]
|
|
return super()._filter_or_exclude(negate, *args, **kwargs)
|
|
|
|
|
|
class ActualOnlyManager(models.Manager):
|
|
def get_queryset(self):
|
|
queryset = super().get_queryset()
|
|
if not settings.DEBUG:
|
|
queryset = queryset.exclude(status=STATUS_DELETED)
|
|
return queryset
|
|
|
|
|
|
class ActiveOnlyManager(models.Manager):
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(status=STATUS_ACTIVE)
|
|
|
|
|
|
class DeletedManager(models.Manager):
|
|
def get_queryset(self):
|
|
return super().get_queryset().filter(status=STATUS_DELETED)
|
|
|
|
|
|
class ActualOnlyTreeManager(mptt_managers.TreeManager, ActualOnlyManager):
|
|
_base_manager = None
|
|
|
|
|
|
class ActiveOnlyTreeManager(mptt_managers.TreeManager, ActiveOnlyManager):
|
|
_base_manager = None
|
|
|
|
|
|
class DeletedTreeManager(mptt_managers.TreeManager, DeletedManager):
|
|
_base_manager = None
|
|
|
|
|
|
class AbstractDateTimeModel(models.Model):
|
|
create_at = models.DateTimeField(_('создан в'), auto_now_add=True)
|
|
updated_at = models.DateTimeField(_('обновлен'), auto_now=True)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
# @TODO: translate into english and use translation
|
|
class AbstractStatusModel(AbstractDateTimeModel):
|
|
status = models.SmallIntegerField(_('статус'), default=STATUS_DEFAULT, choices=STATUS_CHOICES)
|
|
|
|
objects = ActualOnlyManager()
|
|
deleted = DeletedManager()
|
|
active = ActiveOnlyManager()
|
|
|
|
@property
|
|
def is_active(self):
|
|
return self.status == STATUS_ACTIVE
|
|
|
|
@is_active.setter
|
|
def is_active(self, value):
|
|
if value:
|
|
self.status = STATUS_ACTIVE
|
|
else:
|
|
self.status = STATUS_DEFAULT
|
|
|
|
def delete(self, using=None, keep_parents=False):
|
|
self.status = STATUS_DELETED
|
|
self.save(using=using)
|
|
|
|
def delete_from_base(self, using=None, keep_parents=False):
|
|
return super().delete(using, keep_parents)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
class AbstractStatusMPTTModel(mptt_models.MPTTModel, AbstractStatusModel):
|
|
objects = ActualOnlyTreeManager()
|
|
deleted = DeletedTreeManager()
|
|
active = ActiveOnlyTreeManager()
|
|
|
|
@property
|
|
def viewname(self):
|
|
raise NotImplementedError
|
|
|
|
@property
|
|
def viewname_kwargs(self):
|
|
raise NotImplementedError
|
|
|
|
def get_absolute_url(self):
|
|
return reverse_lazy(self.viewname, kwargs=self.viewname_kwargs)
|
|
|
|
class Meta:
|
|
abstract = True
|
|
|
|
|
|
class Currency(AbstractDateTimeModel):
|
|
name = models.CharField(_('название'), max_length=255)
|
|
code = models.CharField(_('код валюты'), max_length=64)
|
|
sign = models.CharField(_('символ валюты'), max_length=10, blank=True, null=True)
|
|
value = models.DecimalField(_('Курс'), max_digits=6, decimal_places=2, help_text=_('Указывается в рублях'))
|
|
|
|
def __str__(self):
|
|
return self.name
|
|
|
|
class Meta:
|
|
verbose_name = _('Валюта')
|
|
verbose_name_plural = _('Валюта')
|
|
|
|
|
|
class City(AbstractDateTimeModel):
|
|
name = models.CharField(_('Город'), max_length=255)
|
|
|
|
class Meta:
|
|
verbose_name = _('Город')
|
|
verbose_name_plural = _('Города')
|
|
|
|
|
|
class Certificate(AbstractStatusModel):
|
|
def upload_file_to(self, filename):
|
|
return "certificates/{filename}".format(**{
|
|
'category': self.name,
|
|
'filename': filename
|
|
})
|
|
|
|
name = models.CharField(_('Название'), max_length=255)
|
|
image = models.FileField(_('Изображение'), upload_to=upload_file_to, blank=True,null=True)
|
|
preview = models.FileField(_('Миниатюрка'), upload_to=upload_file_to)
|
|
|
|
class Meta:
|
|
verbose_name = _('Сертификат')
|
|
verbose_name_plural = _('Сертификаты')
|
|
|