From e3ec65a118fe3dea5aa46ce0eeea524b5891e37b Mon Sep 17 00:00:00 2001 From: Sayyid Hamid Mahdavi Date: Tue, 16 Sep 2025 21:37:32 +0330 Subject: [PATCH] end of day --- apps/promotions/admin.py | 3 +- .../migrations/0005_event_plan_event_list.py | 32 ++++++++++++++++++ apps/promotions/models.py | 33 +++++++++++++------ 3 files changed, 57 insertions(+), 11 deletions(-) create mode 100644 apps/promotions/migrations/0005_event_plan_event_list.py diff --git a/apps/promotions/admin.py b/apps/promotions/admin.py index 44d9a8a..2551214 100644 --- a/apps/promotions/admin.py +++ b/apps/promotions/admin.py @@ -2,9 +2,10 @@ from functools import update_wrapper from django.contrib import admin -from .models import Promotion, Plan +from .models import Promotion, Plan, Event admin.site.register(Plan) admin.site.register(Promotion) +admin.site.register(Event) diff --git a/apps/promotions/migrations/0005_event_plan_event_list.py b/apps/promotions/migrations/0005_event_plan_event_list.py new file mode 100644 index 0000000..b554a2d --- /dev/null +++ b/apps/promotions/migrations/0005_event_plan_event_list.py @@ -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), + ), + ] diff --git a/apps/promotions/models.py b/apps/promotions/models.py index 43a5cc9..5a3def0 100644 --- a/apps/promotions/models.py +++ b/apps/promotions/models.py @@ -16,15 +16,19 @@ class EventQuerySet(models.QuerySet): class Event(BaseModel): 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() + def __str__(self): + return self.label + def analyze(self): for plan in Plan.objects.get_related_to_event(self): plan.process_event(self) + class PlanQuerySet(models.QuerySet): # this is for list of discount code for example @@ -65,20 +69,29 @@ class Plan(BaseModel): def calculate_promotion(self, **kwargs): handler = self.handler self.base_amount = kwargs.get('base_amount', 0) - self.promotion_amount = handler.calculate(**kwargs) - return self.promotion_amount + return handler.calculate(**kwargs) - def reserve_promotion(self, promotion): + def reserve_promotion_amount(self, amount): updated = False - if self.balance >= promotion.promotion_amount: - updated = Plan.objects.filter(pk=self.pk, balance__gte=promotion.promotion_amount).update( - balance=F('balance') - promotion.promotion_amount + if amount and self.balance >= amount: + updated = Plan.objects.filter(pk=self.pk, balance__gte=amount).update( + balance=F('balance') - amount ) return updated def process_event(self, event=None): - promotion, created = Promotion.objects.get_or_create() - promotion.promote() + referral_code = event.data.get('referral_code') + 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): @@ -127,7 +140,7 @@ class Promotion(BaseModel): def promote(self, **kwargs): 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, same_ok=False, raise_exception=True)