67 lines
2.7 KiB
Python
67 lines
2.7 KiB
Python
![]() |
from datetime import datetime
|
||
|
from decimal import Decimal
|
||
|
from django.db import models
|
||
|
from django.utils import timezone
|
||
|
from django.db.models import F, Case, When, Max, ExpressionWrapper, Subquery, OuterRef
|
||
|
from users.models import BetTransaction
|
||
|
|
||
|
|
||
|
class AuctionManager(models.Manager):
|
||
|
def get_queryset(self):
|
||
|
return super().get_queryset().annotate(
|
||
|
_end_time=ExpressionWrapper(
|
||
|
F('initial_end_time') + F('last_call_delta') * F('times_postponed'),
|
||
|
output_field=models.DateTimeField()
|
||
|
)
|
||
|
).annotate(_is_active=Case(
|
||
|
When(_end_time__gt=timezone.now(), then=True),
|
||
|
default=False,
|
||
|
)).annotate(
|
||
|
_min_bet_value=Case(
|
||
|
When(bets__isnull=True, then=F('initial_cost')),
|
||
|
default=Subquery(BetTransaction.objects.filter(bet__auction=OuterRef('pk')).order_by('-value').values('value')[:1]) + Decimal('0.01')
|
||
|
)
|
||
|
).distinct()
|
||
|
|
||
|
|
||
|
class Auction(models.Model):
|
||
|
class Meta:
|
||
|
verbose_name = 'Аукцион'
|
||
|
verbose_name_plural = 'Аукционы'
|
||
|
|
||
|
product = models.ForeignKey('auction.Product', related_name='auctions', on_delete=models.CASCADE,
|
||
|
verbose_name='Товар')
|
||
|
quantity = models.PositiveIntegerField(verbose_name='Количество победителей')
|
||
|
betters = models.ManyToManyField('users.TGUser', through='auction.Bet', related_name='auctions',
|
||
|
verbose_name='Поставившие ставку')
|
||
|
initial_end_time = models.DateTimeField(verbose_name='Изначальная дата окончания')
|
||
|
last_call_delta = models.DurationField(verbose_name='Время последнего шага')
|
||
|
times_postponed = models.IntegerField(default=0, verbose_name='Количество переносов')
|
||
|
commission = models.DecimalField(decimal_places=2, max_digits=5, verbose_name='Комиссия',
|
||
|
help_text='Десятичная дробь')
|
||
|
initial_cost = models.DecimalField(decimal_places=2, max_digits=102, verbose_name='Начальная стоимость')
|
||
|
|
||
|
objects = AuctionManager()
|
||
|
|
||
|
def __str__(self):
|
||
|
return f'Аукцион №{self.pk}'
|
||
|
|
||
|
def check_postpone(self):
|
||
|
if timezone.now() - self.last_call_delta <= self.end_time <= timezone.now():
|
||
|
self.times_postponed = F('times_postponed') + 1
|
||
|
self.save()
|
||
|
|
||
|
@property
|
||
|
def end_time(self):
|
||
|
return self._end_time
|
||
|
|
||
|
@property
|
||
|
def is_active(self):
|
||
|
return self._is_active
|
||
|
|
||
|
@property
|
||
|
def min_bet_value(self):
|
||
|
return self._min_bet_value
|
||
|
|
||
|
|