promotions create
This commit is contained in:
parent
e3ec65a118
commit
ef7adea815
4 changed files with 70 additions and 18 deletions
|
|
@ -9,13 +9,13 @@ from utils.clients.wallet_client import deposit_to_user_wallet_submit, deposit_t
|
||||||
logger = logging.getLogger("promotion_handler")
|
logger = logging.getLogger("promotion_handler")
|
||||||
|
|
||||||
class PromotionTypeChoices(models.TextChoices):
|
class PromotionTypeChoices(models.TextChoices):
|
||||||
WALLET_PERCENTAGE = 'wallet percentage', _('Wallet percentage')
|
PERCENTAGE = 'percentage', _('percentage')
|
||||||
OTHERS = 'others', _('others')
|
OTHERS = 'others', _('others')
|
||||||
|
|
||||||
@enum_property
|
@enum_property
|
||||||
def handler(self):
|
def handler(self):
|
||||||
if self.name == self.WALLET_PERCENTAGE.name:
|
if self.name == self.PERCENTAGE.name:
|
||||||
return WalletPercentageHandler
|
return PercentageHandler
|
||||||
|
|
||||||
elif self.name == self.OTHERS.name:
|
elif self.name == self.OTHERS.name:
|
||||||
return OtherHandler
|
return OtherHandler
|
||||||
|
|
@ -37,7 +37,7 @@ class BasePromotionHandler:
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
|
|
||||||
class WalletPercentageHandler(BasePromotionHandler):
|
class PercentageHandler(BasePromotionHandler):
|
||||||
def calculate(self, **kwargs):
|
def calculate(self, **kwargs):
|
||||||
base_amount = kwargs.get('base_amount', 0)
|
base_amount = kwargs.get('base_amount', 0)
|
||||||
|
|
||||||
|
|
@ -49,6 +49,7 @@ class WalletPercentageHandler(BasePromotionHandler):
|
||||||
return promotion_amount
|
return promotion_amount
|
||||||
|
|
||||||
def promote(self, promotion, **kwargs):
|
def promote(self, promotion, **kwargs):
|
||||||
|
pass
|
||||||
payee_type = self.policy.get('payee_type')
|
payee_type = self.policy.get('payee_type')
|
||||||
payee_uuid = self.policy.get('payee_uuid')
|
payee_uuid = self.policy.get('payee_uuid')
|
||||||
|
|
||||||
|
|
|
||||||
18
apps/promotions/migrations/0006_rename_details_event_data.py
Normal file
18
apps/promotions/migrations/0006_rename_details_event_data.py
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
# Generated by Django 5.2.6 on 2025-09-18 11:22
|
||||||
|
|
||||||
|
from django.db import migrations
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('promotions', '0005_event_plan_event_list'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.RenameField(
|
||||||
|
model_name='event',
|
||||||
|
old_name='details',
|
||||||
|
new_name='data',
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -0,0 +1,28 @@
|
||||||
|
# Generated by Django 5.2.6 on 2025-09-20 11:25
|
||||||
|
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('promotions', '0006_rename_details_event_data'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='plan',
|
||||||
|
name='max_amount',
|
||||||
|
field=models.FloatField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='plan',
|
||||||
|
name='min_amount',
|
||||||
|
field=models.FloatField(blank=True, null=True),
|
||||||
|
),
|
||||||
|
migrations.AlterField(
|
||||||
|
model_name='plan',
|
||||||
|
name='promotion_type',
|
||||||
|
field=models.CharField(choices=[('percentage', 'percentage'), ('others', 'others')], db_index=True, max_length=64, verbose_name='promotion type'),
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -6,6 +6,7 @@ from django.utils import timezone
|
||||||
from oauth2_provider.settings import oauth2_settings
|
from oauth2_provider.settings import oauth2_settings
|
||||||
|
|
||||||
from apps.promotions.handlers import PromotionTypeChoices, BasePromotionHandler
|
from apps.promotions.handlers import PromotionTypeChoices, BasePromotionHandler
|
||||||
|
from apps.users.models import User
|
||||||
from utils.models import BaseModel
|
from utils.models import BaseModel
|
||||||
|
|
||||||
from django.utils.translation import gettext_lazy as _
|
from django.utils.translation import gettext_lazy as _
|
||||||
|
|
@ -14,6 +15,7 @@ from django.utils.translation import gettext_lazy as _
|
||||||
class EventQuerySet(models.QuerySet):
|
class EventQuerySet(models.QuerySet):
|
||||||
pass
|
pass
|
||||||
|
|
||||||
|
|
||||||
class Event(BaseModel):
|
class Event(BaseModel):
|
||||||
label = models.CharField(max_length=255, db_index=True)
|
label = models.CharField(max_length=255, db_index=True)
|
||||||
data = models.JSONField() # from to amount application user etc
|
data = models.JSONField() # from to amount application user etc
|
||||||
|
|
@ -25,10 +27,10 @@ class Event(BaseModel):
|
||||||
|
|
||||||
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):
|
||||||
|
print(plan)
|
||||||
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
|
||||||
|
|
@ -48,11 +50,13 @@ class Plan(BaseModel):
|
||||||
event_list = models.JSONField(default=list)
|
event_list = models.JSONField(default=list)
|
||||||
title = models.CharField(max_length=255, verbose_name=_('title'), db_index=True)
|
title = models.CharField(max_length=255, verbose_name=_('title'), db_index=True)
|
||||||
description = models.TextField(verbose_name=_('description'), blank=True)
|
description = models.TextField(verbose_name=_('description'), blank=True)
|
||||||
promotion_type = models.CharField(max_length=64, verbose_name=_('promotion type'), db_index=True, choices=PromotionTypeChoices.choices)
|
promotion_type = models.CharField(max_length=64, verbose_name=_('promotion type'), db_index=True,
|
||||||
|
choices=PromotionTypeChoices.choices)
|
||||||
|
min_amount = models.FloatField(null=True, blank=True)
|
||||||
|
max_amount = models.FloatField(null=True, blank=True)
|
||||||
policy = models.JSONField(default=dict, verbose_name=_('policy'), null=True, blank=True)
|
policy = models.JSONField(default=dict, verbose_name=_('policy'), null=True, blank=True)
|
||||||
balance = models.IntegerField(verbose_name=_('balance'), default=0)
|
balance = models.IntegerField(verbose_name=_('balance'), default=0)
|
||||||
|
|
||||||
|
|
||||||
objects = PlanQuerySet.as_manager()
|
objects = PlanQuerySet.as_manager()
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
@ -68,7 +72,7 @@ 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)
|
||||||
return handler.calculate(**kwargs)
|
return handler.calculate(**kwargs)
|
||||||
|
|
||||||
def reserve_promotion_amount(self, amount):
|
def reserve_promotion_amount(self, amount):
|
||||||
|
|
@ -80,14 +84,20 @@ class Plan(BaseModel):
|
||||||
return updated
|
return updated
|
||||||
|
|
||||||
def process_event(self, event=None):
|
def process_event(self, event=None):
|
||||||
|
print(event)
|
||||||
referral_code = event.data.get('referral_code')
|
referral_code = event.data.get('referral_code')
|
||||||
user_uuid = event.data.get('user_uuid')
|
user_uuid = event.data.get('user_uuid')
|
||||||
promotion_amount = self.calculate_promotion()
|
promotion_amount = self.calculate_promotion(**self.policy)
|
||||||
if referral_code and promotion_amount and not self.promotions.filter(user_id=referral_code, data__user_uuid=user_uuid).exists():
|
if referral_code and promotion_amount and not self.promotions.filter(user_id=referral_code,
|
||||||
|
data__user_uuid=user_uuid).exists():
|
||||||
|
referral_user, created = User.objects.get_or_create(uuid=referral_code)
|
||||||
|
user = User.objects.get_or_create(uuid=user_uuid)
|
||||||
with transaction.atomic():
|
with transaction.atomic():
|
||||||
if self.reserve_promotion_amount(promotion_amount):
|
if self.reserve_promotion_amount(promotion_amount):
|
||||||
promotion, created = Promotion.objects.get_or_create()
|
promotion, created = Promotion.objects.get_or_create(plan=self, user=referral_user, defaults={
|
||||||
if created:
|
"data": event.data
|
||||||
|
})
|
||||||
|
if not created:
|
||||||
raise Exception('Promotion already reserved')
|
raise Exception('Promotion already reserved')
|
||||||
else:
|
else:
|
||||||
raise Exception('Promotion already reserved')
|
raise Exception('Promotion already reserved')
|
||||||
|
|
@ -139,8 +149,6 @@ class Promotion(BaseModel):
|
||||||
raise Exception(error_message)
|
raise Exception(error_message)
|
||||||
|
|
||||||
def promote(self, **kwargs):
|
def promote(self, **kwargs):
|
||||||
with transaction.atomic():
|
|
||||||
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)
|
||||||
|
|
||||||
|
|
@ -149,6 +157,3 @@ class Promotion(BaseModel):
|
||||||
self.change_state(from_states=[Promotion.StateChoices.ASSIGNED], to_state=Promotion.StateChoices.PROMOTED)
|
self.change_state(from_states=[Promotion.StateChoices.ASSIGNED], to_state=Promotion.StateChoices.PROMOTED)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue