feature/allow-users #1
3 changed files with 79 additions and 3 deletions
|
|
@ -2,7 +2,7 @@ from functools import update_wrapper
|
|||
|
||||
from django.contrib import admin
|
||||
|
||||
from .models import Promotion, Plan, Event, Recipient, EventSaver
|
||||
from .models import Promotion, Plan, Event, Recipient, EventSaver, AllowedUser
|
||||
|
||||
class PromotionAdmin(admin.ModelAdmin):
|
||||
list_display = ['user_uuid', 'plan', 'promotion_amount', 'recipient', 'event', 'created_at']
|
||||
|
|
@ -10,9 +10,13 @@ class PromotionAdmin(admin.ModelAdmin):
|
|||
class PlanAdmin(admin.ModelAdmin):
|
||||
list_display = ['uuid', 'title', 'balance']
|
||||
|
||||
class AllowedUserAdmin(admin.ModelAdmin):
|
||||
list_display = ['user', 'recipient', 'created_at']
|
||||
|
||||
admin.site.register(Plan, PlanAdmin)
|
||||
admin.site.register(Promotion, PromotionAdmin)
|
||||
admin.site.register(Event)
|
||||
admin.site.register(EventSaver)
|
||||
admin.site.register(Recipient)
|
||||
admin.site.register(AllowedUser, AllowedUserAdmin)
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,40 @@
|
|||
import uuid
|
||||
|
||||
from django.conf import settings
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
dependencies = [
|
||||
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||
('promotions', '0008_plan_balance_holder_alter_plan_description_details'),
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.AddField(
|
||||
model_name='recipient',
|
||||
name='access_type',
|
||||
field=models.CharField(choices=[('restricted', 'restricted'), ('public', 'public')],
|
||||
db_index=True, default='public', max_length=64, verbose_name='access type'),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='AllowedUser',
|
||||
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)),
|
||||
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='allowed_recipients', to=settings.AUTH_USER_MODEL)),
|
||||
('recipient', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE,
|
||||
related_name='allowed_users', to='promotions.recipient')),
|
||||
],
|
||||
options={
|
||||
'constraints': [
|
||||
models.UniqueConstraint(fields=('user', 'recipient'), name='unique_allowed_user_recipient'),
|
||||
],
|
||||
},
|
||||
),
|
||||
]
|
||||
|
|
@ -135,9 +135,11 @@ class Plan(BaseModel):
|
|||
def __str__(self):
|
||||
return self.title
|
||||
|
||||
def get_configured_promotion_amount(self):
|
||||
def get_configured_promotion_amount(self, user_uuid=None):
|
||||
amount = 0
|
||||
for recipient in self.recipients.filter(recipient_uuid_field='->event:user'): #TODO: instead of hard code use better soloution
|
||||
if not recipient.is_user_allowed(user_uuid):
|
||||
continue
|
||||
base_amount, promotion_amount = recipient.get_promotion_amount()
|
||||
amount += promotion_amount
|
||||
return amount
|
||||
|
|
@ -180,12 +182,19 @@ class Plan(BaseModel):
|
|||
return updated
|
||||
|
||||
|
||||
class RecipientTypeChoices(models.TextChoices):
|
||||
RESTRICTED = 'restricted', _('restricted')
|
||||
PUBLIC = 'public', _('public')
|
||||
|
||||
|
||||
class Recipient(BaseModel):
|
||||
label = models.CharField(max_length=255, db_index=True)
|
||||
plan = models.ForeignKey(Plan, on_delete=models.PROTECT, related_name='recipients', null=True, blank=True)
|
||||
wallet_uuid = models.UUIDField(null=True, blank=True)
|
||||
promotion_type = models.CharField(max_length=64, verbose_name=_('promotion type'), db_index=True,
|
||||
choices=PromotionTypeChoices.choices, null=True, blank=True)
|
||||
access_type = models.CharField(max_length=64, verbose_name=_('access type'), db_index=True,
|
||||
choices=RecipientTypeChoices.choices, default=RecipientTypeChoices.PUBLIC)
|
||||
|
||||
recipient_uuid_field = models.CharField(max_length=255, db_index=True)
|
||||
base_amount_field = models.CharField(max_length=255, db_index=True)
|
||||
|
|
@ -207,6 +216,13 @@ class Recipient(BaseModel):
|
|||
def get_wallet_category_uuid(self):
|
||||
return self.wallet_uuid or settings.WALLET_PROMOTION_CATEGORY_UUID
|
||||
|
||||
def is_user_allowed(self, user_uuid):
|
||||
if self.access_type != RecipientTypeChoices.RESTRICTED:
|
||||
return True
|
||||
if not user_uuid:
|
||||
return False
|
||||
return self.allowed_users.filter(user__uuid=user_uuid).exists()
|
||||
|
||||
def get_recipient_uuid(self, plan=None, event=None):
|
||||
if ':' in self.recipient_uuid_field and not self.recipient_uuid_field.startswith('QS:'):
|
||||
filters_key_values, recipient_candidate = self.recipient_uuid_field.split('->')
|
||||
|
|
@ -315,6 +331,9 @@ class Recipient(BaseModel):
|
|||
if not recipient:
|
||||
return None
|
||||
|
||||
if not self.is_user_allowed(recipient):
|
||||
return None
|
||||
|
||||
base_amount, promotion_amount = self.get_promotion_amount(plan=plan, event=event)
|
||||
promotion, created = Promotion.objects.get_or_create(
|
||||
promotion_amount=promotion_amount,
|
||||
|
|
@ -341,6 +360,19 @@ class Recipient(BaseModel):
|
|||
return None
|
||||
|
||||
|
||||
class AllowedUser(BaseModel):
|
||||
user = models.ForeignKey(settings.AUTH_USER_MODEL, on_delete=models.CASCADE, related_name='allowed_recipients')
|
||||
recipient = models.ForeignKey(Recipient, on_delete=models.CASCADE, related_name='allowed_users')
|
||||
|
||||
class Meta:
|
||||
constraints = [
|
||||
models.UniqueConstraint(fields=['user', 'recipient'], name='unique_allowed_user_recipient')
|
||||
]
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.user} -> {self.recipient}"
|
||||
|
||||
|
||||
class PaymentStateChoices(models.IntegerChoices):
|
||||
CREATED = 1, _('created')
|
||||
DELAYED = 2, _('delayed') # delayed as user wish
|
||||
|
|
@ -365,7 +397,7 @@ def get_event_status_for_user(user_uuid, event_label):
|
|||
if not processed:
|
||||
plan = Plan.objects.filter(event_list__icontains=event_label).first()
|
||||
if plan:
|
||||
promotion_amount = plan.get_configured_promotion_amount()
|
||||
promotion_amount = plan.get_configured_promotion_amount(user_uuid=user_uuid)
|
||||
return {
|
||||
'event_label': event_label,
|
||||
'processed': processed,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue