get plan details
This commit is contained in:
parent
81e3e7776d
commit
61f3c8a920
6 changed files with 94 additions and 37 deletions
|
|
@ -0,0 +1,29 @@
|
||||||
|
# Generated by Django 6.0.2 on 2026-02-22 10:12
|
||||||
|
|
||||||
|
import django_minio_backend.models
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
('promotions', '0006_event_promotions_event_data_bc656abc_and_more'),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AlterModelOptions(
|
||||||
|
name='event',
|
||||||
|
options={'ordering': ('-created_at',)},
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='plan',
|
||||||
|
name='banner',
|
||||||
|
field=models.ImageField(blank=True, null=True, storage=django_minio_backend.models.MinioBackend(), upload_to=django_minio_backend.models.iso_date_prefix),
|
||||||
|
),
|
||||||
|
migrations.AddField(
|
||||||
|
model_name='plan',
|
||||||
|
name='description_details',
|
||||||
|
field=models.JSONField(blank=True, default={}, verbose_name='description details'),
|
||||||
|
preserve_default=False,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
|
@ -5,6 +5,7 @@ from django.contrib.postgres.indexes import GinIndex
|
||||||
from django.db import models, transaction
|
from django.db import models, transaction
|
||||||
from django.db.models import F
|
from django.db.models import F
|
||||||
from django.utils import timezone
|
from django.utils import timezone
|
||||||
|
from django_minio_backend import MinioBackend, iso_date_prefix
|
||||||
|
|
||||||
from oauth2_provider.settings import oauth2_settings
|
from oauth2_provider.settings import oauth2_settings
|
||||||
|
|
||||||
|
|
@ -105,7 +106,9 @@ class Plan(BaseModel):
|
||||||
null=True, blank=True)
|
null=True, blank=True)
|
||||||
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)
|
||||||
|
banner = models.ImageField(null=True, blank=True, storage=MinioBackend(), upload_to=iso_date_prefix)
|
||||||
description = models.TextField(verbose_name=_('description'), blank=True)
|
description = models.TextField(verbose_name=_('description'), blank=True)
|
||||||
|
description_details = models.JSONField(verbose_name=_('description details'), blank=True)
|
||||||
processor = models.CharField(max_length=64, verbose_name=_('processor'), db_index=True,
|
processor = models.CharField(max_length=64, verbose_name=_('processor'), db_index=True,
|
||||||
choices=ProcessorTypeChoices.choices) # TODO: processor type
|
choices=ProcessorTypeChoices.choices) # TODO: processor type
|
||||||
data = models.JSONField(default=dict, verbose_name=_('data'), null=True, blank=True)
|
data = models.JSONField(default=dict, verbose_name=_('data'), null=True, blank=True)
|
||||||
|
|
|
||||||
|
|
@ -1,6 +1,6 @@
|
||||||
from rest_framework import serializers
|
from rest_framework import serializers
|
||||||
|
|
||||||
from .models import Promotion, Plan, Event
|
from .models import Promotion, Plan, Event, Recipient
|
||||||
|
|
||||||
|
|
||||||
class PromotionSerializer(serializers.ModelSerializer):
|
class PromotionSerializer(serializers.ModelSerializer):
|
||||||
|
|
@ -74,3 +74,27 @@ class PromoteSerializer(serializers.ModelSerializer):
|
||||||
"label",
|
"label",
|
||||||
"data",
|
"data",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserRecipientSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Recipient
|
||||||
|
fields = ['label',
|
||||||
|
"base_amount_field"]
|
||||||
|
|
||||||
|
|
||||||
|
class UserPlanSerializer(serializers.ModelSerializer):
|
||||||
|
recipients = UserRecipientSerializer(many=True, read_only=True)
|
||||||
|
class Meta:
|
||||||
|
model = Plan
|
||||||
|
fields = ("title",
|
||||||
|
'banner',
|
||||||
|
"description",
|
||||||
|
"description_details",
|
||||||
|
"recipients",
|
||||||
|
)
|
||||||
|
read_only_fields = ("title", "description", "description_details", 'banner', "recipients")
|
||||||
|
|
||||||
|
# def get_promotion_amount(self, obj):
|
||||||
|
# user = self.context['request'].user
|
||||||
|
# return obj.calculate_promotion(user)
|
||||||
|
|
|
||||||
|
|
@ -12,7 +12,7 @@ app_name = 'promotions'
|
||||||
router = DefaultRouter()
|
router = DefaultRouter()
|
||||||
# router.register(r'application', views.ApplicationPromotionViewSet, basename='application_promotions')
|
# router.register(r'application', views.ApplicationPromotionViewSet, basename='application_promotions')
|
||||||
# router.register(r'events', views.ApplicationViewSet, basename='application-events')
|
# router.register(r'events', views.ApplicationViewSet, basename='application-events')
|
||||||
# router.register(r'plans', views.UserViewSet, basename='user')
|
router.register(r'plans', views.UserPlanViewSet, basename='user-plans')
|
||||||
|
|
||||||
# urlpatterns =
|
# urlpatterns =
|
||||||
|
|
||||||
|
|
@ -20,7 +20,6 @@ urlpatterns = [
|
||||||
path('api/v1/plans/<plan>/', ApplicationPromoteUserApiView.as_view(), name='promotion-create'),
|
path('api/v1/plans/<plan>/', ApplicationPromoteUserApiView.as_view(), name='promotion-create'),
|
||||||
path('api/v1/plans/<plan>/promotins', ApplicationPromotionListApiView.as_view(), name='promotion-list'),
|
path('api/v1/plans/<plan>/promotins', ApplicationPromotionListApiView.as_view(), name='promotion-list'),
|
||||||
path('api/v1/events/submit', ApplicationEventSubmitAPIView.as_view(), name='event-create'),
|
path('api/v1/events/submit', ApplicationEventSubmitAPIView.as_view(), name='event-create'),
|
||||||
path('api/v1/events/get', ApplicationEventRetrieveAPIView.as_view(), name='event-retrieve'),
|
# path('api/v1/events/get', ApplicationEventRetrieveAPIView.as_view(), name='event-retrieve'),
|
||||||
path('api/v1/', include(router.urls), name='events'),
|
path('api/v2/', include(router.urls)),
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
|
||||||
|
|
@ -10,7 +10,7 @@ from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRe
|
||||||
from apps.gooyal_oauth2.utils import get_application
|
from apps.gooyal_oauth2.utils import get_application
|
||||||
from utils.exceptions import UnprocessableEntity
|
from utils.exceptions import UnprocessableEntity
|
||||||
from .models import Plan, Promotion, EventSaver
|
from .models import Plan, Promotion, EventSaver
|
||||||
from .serializers import PlanSerializer, PromotionSerializer, EventSerializer, PromoteSerializer
|
from .serializers import PlanSerializer, PromotionSerializer, EventSerializer, PromoteSerializer, UserPlanSerializer
|
||||||
from .tasks import analyze_event_task
|
from .tasks import analyze_event_task
|
||||||
from ..users.models import User
|
from ..users.models import User
|
||||||
|
|
||||||
|
|
@ -100,14 +100,15 @@ class ApplicationViewSet(
|
||||||
serializer.instance = event
|
serializer.instance = event
|
||||||
|
|
||||||
|
|
||||||
class UserViewSet(mixins.RetrieveModelMixin,
|
class UserPlanViewSet(mixins.RetrieveModelMixin,
|
||||||
mixins.ListModelMixin,
|
# mixins.ListModelMixin,
|
||||||
|
mixins.CreateModelMixin,
|
||||||
GenericViewSet):
|
GenericViewSet):
|
||||||
serializer_class = PlanSerializer
|
serializer_class = UserPlanSerializer
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
||||||
required_alternate_scopes = {
|
required_alternate_scopes = {
|
||||||
"GET": [["promotions.user.self-plans:list-retrieve"]],
|
"GET": [["promotions.user.plans:list-retrieve"]],
|
||||||
"POST": [["promotions.user.self-plans:list-retrieve"]],
|
"POST": [["promotions.user.plans:list-retrieve"]],
|
||||||
}
|
}
|
||||||
|
|
||||||
def get_queryset(self):
|
def get_queryset(self):
|
||||||
|
|
@ -117,39 +118,39 @@ class UserViewSet(mixins.RetrieveModelMixin,
|
||||||
queryset = Plan.objects.all()
|
queryset = Plan.objects.all()
|
||||||
return queryset
|
return queryset
|
||||||
|
|
||||||
@extend_schema(responses=PlanSerializer(many=True))
|
# @extend_schema(responses=PlanSerializer(many=True))
|
||||||
@action(detail=False, methods=['POST'], serializer_class=PlanSerializer)
|
# @action(detail=False, methods=['POST'], serializer_class=PlanSerializer)
|
||||||
def available(self, request):
|
# def available(self, request):
|
||||||
serializer = self.get_serializer(data=self.request.data)
|
# serializer = self.get_serializer(data=self.request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
# serializer.is_valid(raise_exception=True)
|
||||||
print(serializer.validated_data)
|
# print(serializer.validated_data)
|
||||||
plans = self.paginate_queryset(self.filter_queryset(self.get_queryset()))
|
# plans = self.paginate_queryset(self.filter_queryset(self.get_queryset()))
|
||||||
for plan in plans:
|
# for plan in plans:
|
||||||
plan.calculate_promotion(**serializer.validated_data)
|
# plan.calculate_promotion(**serializer.validated_data)
|
||||||
serializer = self.get_serializer(plans, many=True)
|
# serializer = self.get_serializer(plans, many=True)
|
||||||
return self.get_paginated_response(serializer.data)
|
# return self.get_paginated_response(serializer.data)
|
||||||
|
|
||||||
@action(detail=True, methods=['POST'], serializer_class=EventSerializer)
|
@action(detail=True, methods=['POST'], serializer_class=PromoteSerializer)
|
||||||
def promote(self, request, pk=None):
|
def promote(self, request, pk=None):
|
||||||
serializer = self.get_serializer(data=self.request.data)
|
plan = self.get_object()
|
||||||
|
serializer = self.get_serializer(data=request.data)
|
||||||
serializer.is_valid(raise_exception=True)
|
serializer.is_valid(raise_exception=True)
|
||||||
|
data = serializer.validated_data
|
||||||
if hasattr(self.request, 'user'):
|
|
||||||
user = self.request.user
|
|
||||||
else:
|
|
||||||
user = None
|
|
||||||
|
|
||||||
application = get_application(self.request)
|
application = get_application(self.request)
|
||||||
# EventSaver.objects.first(event_label=serializer.validated_data['event_label'], valid_application__contains=application.uuid)
|
|
||||||
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
|
event_saver: EventSaver = EventSaver.objects.filter(event_label=serializer.validated_data['label']).first()
|
||||||
try:
|
|
||||||
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
|
|
||||||
except Exception as e:
|
|
||||||
raise exceptions.ValidationError(str(e))
|
|
||||||
|
|
||||||
plan: Plan = self.get_object()
|
user = self.request.user.pk or serializer.validated_data['user']
|
||||||
|
# try:
|
||||||
|
event = event_saver.save_event(user=user, application=application, **serializer.validated_data)
|
||||||
|
# except Exception as e:
|
||||||
|
# raise exceptions.ValidationError(str(e))
|
||||||
|
|
||||||
return
|
result_list = plan.process_event(event)
|
||||||
|
data["promotions"] = result_list
|
||||||
|
|
||||||
|
headers = self.get_success_headers(serializer.data)
|
||||||
|
return Response(serializer.data, status=status.HTTP_201_CREATED, headers=headers)
|
||||||
|
|
||||||
|
|
||||||
class ApplicationPromoteUserApiView(CreateAPIView):
|
class ApplicationPromoteUserApiView(CreateAPIView):
|
||||||
|
|
|
||||||
|
|
@ -36,6 +36,7 @@ INSTALLED_APPS = [
|
||||||
'django.contrib.sessions',
|
'django.contrib.sessions',
|
||||||
'django.contrib.messages',
|
'django.contrib.messages',
|
||||||
'django.contrib.staticfiles',
|
'django.contrib.staticfiles',
|
||||||
|
'django.contrib.postgres',
|
||||||
|
|
||||||
# pip installed apps
|
# pip installed apps
|
||||||
'drf_spectacular',
|
'drf_spectacular',
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue