end of day

This commit is contained in:
Sayyid Hamid Mahdavi 2025-09-16 21:37:32 +03:30
parent 3d55d4eba3
commit e3ec65a118
3 changed files with 57 additions and 11 deletions

View file

@ -2,9 +2,10 @@ from functools import update_wrapper
from django.contrib import admin from django.contrib import admin
from .models import Promotion, Plan from .models import Promotion, Plan, Event
admin.site.register(Plan) admin.site.register(Plan)
admin.site.register(Promotion) admin.site.register(Promotion)
admin.site.register(Event)

View file

@ -0,0 +1,32 @@
# Generated by Django 5.2.6 on 2025-09-16 17:32
import uuid
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('promotions', '0004_promotion_base_amount'),
]
operations = [
migrations.CreateModel(
name='Event',
fields=[
('uuid', models.UUIDField(db_index=True, default=uuid.uuid4, editable=False, primary_key=True, serialize=False, unique=True)),
('created_at', models.DateTimeField(auto_now_add=True, db_index=True)),
('updated_at', models.DateTimeField(auto_now=True, db_index=True)),
('label', models.CharField(db_index=True, max_length=255)),
('details', models.JSONField()),
],
options={
'abstract': False,
},
),
migrations.AddField(
model_name='plan',
name='event_list',
field=models.JSONField(default=list),
),
]

View file

@ -16,15 +16,19 @@ class EventQuerySet(models.QuerySet):
class Event(BaseModel): class Event(BaseModel):
label = models.CharField(max_length=255, db_index=True) label = models.CharField(max_length=255, db_index=True)
details = models.JSONField() # from to amount application user etc data = models.JSONField() # from to amount application user etc
objects = EventQuerySet.as_manager() objects = EventQuerySet.as_manager()
def __str__(self):
return self.label
def analyze(self): def analyze(self):
for plan in Plan.objects.get_related_to_event(self): for plan in Plan.objects.get_related_to_event(self):
plan.process_event(self) plan.process_event(self)
class PlanQuerySet(models.QuerySet): class PlanQuerySet(models.QuerySet):
# this is for list of discount code for example # this is for list of discount code for example
@ -65,20 +69,29 @@ class Plan(BaseModel):
def calculate_promotion(self, **kwargs): def calculate_promotion(self, **kwargs):
handler = self.handler handler = self.handler
self.base_amount = kwargs.get('base_amount', 0) self.base_amount = kwargs.get('base_amount', 0)
self.promotion_amount = handler.calculate(**kwargs) return handler.calculate(**kwargs)
return self.promotion_amount
def reserve_promotion(self, promotion): def reserve_promotion_amount(self, amount):
updated = False updated = False
if self.balance >= promotion.promotion_amount: if amount and self.balance >= amount:
updated = Plan.objects.filter(pk=self.pk, balance__gte=promotion.promotion_amount).update( updated = Plan.objects.filter(pk=self.pk, balance__gte=amount).update(
balance=F('balance') - promotion.promotion_amount balance=F('balance') - amount
) )
return updated return updated
def process_event(self, event=None): def process_event(self, event=None):
promotion, created = Promotion.objects.get_or_create() referral_code = event.data.get('referral_code')
promotion.promote() user_uuid = event.data.get('user_uuid')
promotion_amount = self.calculate_promotion()
if referral_code and promotion_amount and not self.promotions.filter(user_id=referral_code, data__user_uuid=user_uuid).exists():
with transaction.atomic():
if self.reserve_promotion_amount(promotion_amount):
promotion, created = Promotion.objects.get_or_create()
if created:
raise Exception('Promotion already reserved')
else:
raise Exception('Promotion already reserved')
promotion.promote()
class PromotionQuerySet(models.QuerySet): class PromotionQuerySet(models.QuerySet):
@ -127,7 +140,7 @@ class Promotion(BaseModel):
def promote(self, **kwargs): def promote(self, **kwargs):
with transaction.atomic(): with transaction.atomic():
self.plan.reserve_promotion(self) self.plan.reserve_promotion_amount(self)
self.change_state(from_states=[Promotion.StateChoices.CREATED], to_state=Promotion.StateChoices.ASSIGNED, self.change_state(from_states=[Promotion.StateChoices.CREATED], to_state=Promotion.StateChoices.ASSIGNED,
same_ok=False, raise_exception=True) same_ok=False, raise_exception=True)