* Cleanup & optimizations

This commit is contained in:
Phil Zhitnikov 2024-05-21 01:05:55 +04:00
parent 3011d0285d
commit e8d94878c6
5 changed files with 42 additions and 14 deletions

View File

@ -0,0 +1,20 @@
# Generated by Django 4.2.2 on 2024-05-20 21:01
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
class Migration(migrations.Migration):
dependencies = [
('account', '0017_alter_bonusprogramtransaction_type'),
]
operations = [
migrations.AlterField(
model_name='bonusprogramtransaction',
name='user',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='bonus_transactions', to=settings.AUTH_USER_MODEL, verbose_name='Пользователь транзакции'),
),
]

View File

@ -78,7 +78,7 @@ class BonusProgramTransaction(models.Model):
""" Represents the history of all bonus program transactions """ """ Represents the history of all bonus program transactions """
type = models.PositiveSmallIntegerField('Тип транзакции', choices=BonusType.CHOICES) type = models.PositiveSmallIntegerField('Тип транзакции', choices=BonusType.CHOICES)
user = models.ForeignKey('User', verbose_name='Пользователь транзакции', on_delete=models.CASCADE) user = models.ForeignKey('User', verbose_name='Пользователь транзакции', on_delete=models.CASCADE, related_name='bonus_transactions')
date = models.DateTimeField('Дата транзакции', auto_now_add=True) date = models.DateTimeField('Дата транзакции', auto_now_add=True)
amount = models.SmallIntegerField('Количество, руб') amount = models.SmallIntegerField('Количество, руб')
comment = models.CharField('Комментарий', max_length=200, null=True, blank=True) comment = models.CharField('Комментарий', max_length=200, null=True, blank=True)

View File

@ -29,7 +29,7 @@ class ChecklistAdmin(admin.ModelAdmin):
return obj.status_updated_at or obj.created_at return obj.status_updated_at or obj.created_at
def get_queryset(self, request): def get_queryset(self, request):
return Checklist.objects.with_base_related().annotate_price_rub().annotate_commission_rub() return Checklist.objects.with_base_related()
@admin.register(GlobalSettings) @admin.register(GlobalSettings)

View File

@ -195,13 +195,26 @@ def generate_checklist_id():
class ChecklistQuerySet(models.QuerySet): class ChecklistQuerySet(models.QuerySet):
def with_base_related(self): def with_base_related(self):
return self.select_related('manager', 'category', 'payment_method', return self.select_related('manager', 'category', 'category__parent', 'payment_method',
'promocode', 'price_snapshot', 'gift', 'customer') \ 'promocode', 'price_snapshot', 'gift', 'customer') \
.prefetch_related(Prefetch('images', to_attr='_images')) .prefetch_related(Prefetch('images', to_attr='_images'))
def annotate_bonus_used(self):
from account.models import BonusProgramTransaction, BonusType
amount_subquery = Subquery(
BonusProgramTransaction.objects.all()
.filter(type=BonusType.SPENT_PURCHASE,
user_id=OuterRef('customer_id'),
order_id=OuterRef('id'))
.values('amount'))
return self.annotate(_bonus_used=Coalesce(amount_subquery, 0))
def default_ordering(self): def default_ordering(self):
return self.order_by(F('status_updated_at').desc(nulls_last=True)) return self.order_by(F('status_updated_at').desc(nulls_last=True))
# TODO: deprecate
def annotate_price_rub(self): def annotate_price_rub(self):
return self.annotate( return self.annotate(
_yuan_rate=Case( _yuan_rate=Case(
@ -211,6 +224,7 @@ class ChecklistQuerySet(models.QuerySet):
_price_rub=Ceil(F('_yuan_rate') * F('price_yuan')) _price_rub=Ceil(F('_yuan_rate') * F('price_yuan'))
) )
# TODO: deprecate
def annotate_commission_rub(self): def annotate_commission_rub(self):
default_commission = GlobalSettings.load().commission_rub default_commission = GlobalSettings.load().commission_rub
over_150k_commission = F('_price_rub') * settings.COMMISSION_OVER_150K over_150k_commission = F('_price_rub') * settings.COMMISSION_OVER_150K
@ -438,10 +452,6 @@ class Checklist(models.Model):
@property @property
def price_rub(self) -> int: def price_rub(self) -> int:
# Prefer annotated field for calculation
if hasattr(self, '_price_rub'):
return self._price_rub
# Get saved prices # Get saved prices
if self.price_snapshot_id: if self.price_snapshot_id:
yuan_rate = self.price_snapshot.yuan_rate yuan_rate = self.price_snapshot.yuan_rate
@ -501,10 +511,6 @@ class Checklist(models.Model):
@property @property
def commission_rub(self) -> Decimal: def commission_rub(self) -> Decimal:
# Prefer annotated field
if hasattr(self, '_commission_rub'):
return self._commission_rub
# Prefer saved value # Prefer saved value
if self.price_snapshot_id: if self.price_snapshot_id:
return self.price_snapshot.commission_rub return self.price_snapshot.commission_rub
@ -525,6 +531,10 @@ class Checklist(models.Model):
@property @property
def bonus_used(self): def bonus_used(self):
# Prefer annotated field
if hasattr(self, '_bonus_used'):
return self._bonus_used
if self.customer_id is None: if self.customer_id is None:
return 0 return 0

View File

@ -99,7 +99,7 @@ class ChecklistAPI(viewsets.ModelViewSet):
def get_queryset(self): def get_queryset(self):
return Checklist.objects.all().with_base_related() \ return Checklist.objects.all().with_base_related() \
.annotate_price_rub().annotate_commission_rub() \ .annotate_bonus_used() \
.default_ordering() .default_ordering()
def get_object(self): def get_object(self):
@ -191,8 +191,6 @@ class StatisticsAPI(viewsets.GenericViewSet):
# Prepare query to collect the stats # Prepare query to collect the stats
qs = self.get_queryset() \ qs = self.get_queryset() \
.annotate_price_rub() \
.annotate_commission_rub() \
.values('month') \ .values('month') \
.annotate(total=Count('id'), .annotate(total=Count('id'),
total_completed=Count('id'), total_completed=Count('id'),