REFACTOR(promotions): split admin panel into views/serializers/urls subpackages
Restructures the admin promotions/referrals endpoints to match the admin/users folder split used by the sibling advertising service (apps/crm, apps/escrow, apps/stores there): views/admin/, serializers/admin/, and a shared urls/router.py with the two resources as GenericViewSets registered on one DefaultRouter, instead of flat _admin-suffixed modules with separate ListAPIView/RetrieveAPIView classes. Scoped to the admin slice only -- the pre-existing user-token/ application-token views, urls, and serializers keep their original _user/_application file layout and URL namespaces, since converting those too would rename routes tests.py and external callers depend on. filters.py stays a single flat file, matching how advertising's own filters.py is not split into subfolders either. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
parent
d27ae32e27
commit
1d77303f00
16 changed files with 319 additions and 298 deletions
|
|
@ -1,36 +0,0 @@
|
||||||
import django_filters
|
|
||||||
|
|
||||||
from .handlers import ProcessorTypeChoices
|
|
||||||
from .models import Promotion, PaymentStateChoices
|
|
||||||
|
|
||||||
|
|
||||||
class AdminPromotionFilter(django_filters.FilterSet):
|
|
||||||
user_uuid = django_filters.UUIDFilter(field_name='user_uuid')
|
|
||||||
plan = django_filters.UUIDFilter(field_name='plan__uuid')
|
|
||||||
promotion_type = django_filters.ChoiceFilter(field_name='plan__processor', choices=ProcessorTypeChoices.choices)
|
|
||||||
state = django_filters.ChoiceFilter(field_name='state', choices=PaymentStateChoices.choices)
|
|
||||||
event_label = django_filters.CharFilter(field_name='event__label', lookup_expr='exact')
|
|
||||||
created_after = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
|
|
||||||
created_before = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='lte')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = ['user_uuid', 'plan', 'promotion_type', 'state', 'event_label', 'created_after', 'created_before']
|
|
||||||
|
|
||||||
|
|
||||||
class AdminReferralFilter(django_filters.FilterSet):
|
|
||||||
# invited_by == Promotion.user_uuid: in the referral recipient DSL
|
|
||||||
# ("->event:referral") this is who gets paid, i.e. the referrer.
|
|
||||||
invited_by = django_filters.UUIDFilter(field_name='user_uuid')
|
|
||||||
# invited_user lives only in free-form JSON (event.data['user']), so this is a
|
|
||||||
# CharFilter, not UUIDFilter: JSONField key-transform lookups compare against
|
|
||||||
# the stored string, not a native UUID the adapter can serialize.
|
|
||||||
invited_user = django_filters.CharFilter(field_name='event__data__user')
|
|
||||||
plan = django_filters.UUIDFilter(field_name='plan__uuid')
|
|
||||||
state = django_filters.ChoiceFilter(field_name='state', choices=PaymentStateChoices.choices)
|
|
||||||
created_after = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='gte')
|
|
||||||
created_before = django_filters.DateTimeFilter(field_name='created_at', lookup_expr='lte')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = ['invited_user', 'invited_by', 'plan', 'state', 'created_after', 'created_before']
|
|
||||||
|
|
@ -1,188 +0,0 @@
|
||||||
from rest_framework import serializers
|
|
||||||
|
|
||||||
from .models import Promotion, Plan, Event, Recipient
|
|
||||||
|
|
||||||
|
|
||||||
class EventSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Event
|
|
||||||
fields = (
|
|
||||||
"label",
|
|
||||||
"data",
|
|
||||||
"user",
|
|
||||||
"application",
|
|
||||||
)
|
|
||||||
read_only_fields = ('user', 'application')
|
|
||||||
|
|
||||||
|
|
||||||
class PromotionSerializer(serializers.ModelSerializer):
|
|
||||||
# base_amount = serializers.IntegerField(required=True)
|
|
||||||
# promotion_amount = serializers.IntegerField(read_only=True)
|
|
||||||
event = EventSerializer(read_only=True)
|
|
||||||
user = serializers.UUIDField(source='user_uuid')
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = (
|
|
||||||
"uuid",
|
|
||||||
"event",
|
|
||||||
"promotion_amount",
|
|
||||||
"state",
|
|
||||||
"user",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class PlanSerializer(serializers.ModelSerializer):
|
|
||||||
base_amount = serializers.IntegerField(required=True)
|
|
||||||
promotion_amount = serializers.IntegerField(read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Plan
|
|
||||||
fields = ("title",
|
|
||||||
"description",
|
|
||||||
"base_amount",
|
|
||||||
"application",
|
|
||||||
"promotion_amount"
|
|
||||||
)
|
|
||||||
read_only_fields = ('application', "promotion_amount", "title", "description")
|
|
||||||
|
|
||||||
# def get_promotion_amount(self, obj):
|
|
||||||
# user = self.context['request'].user
|
|
||||||
# return obj.calculate_promotion(user)
|
|
||||||
|
|
||||||
|
|
||||||
class PlanPromotSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = (
|
|
||||||
"user",
|
|
||||||
"application",
|
|
||||||
)
|
|
||||||
read_only_fields = ('user', 'application')
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PromoteSerializer(serializers.ModelSerializer):
|
|
||||||
label = serializers.CharField(write_only=True)
|
|
||||||
data = serializers.JSONField(write_only=True)
|
|
||||||
|
|
||||||
promotions = PromotionSerializer(many=True, read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = (
|
|
||||||
"promotions",
|
|
||||||
"label",
|
|
||||||
"data",
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class UserRecipientSerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Recipient
|
|
||||||
fields = ['label',
|
|
||||||
"base_amount_field"]
|
|
||||||
|
|
||||||
|
|
||||||
class PromotionStatusSerializer(serializers.Serializer):
|
|
||||||
event_label = serializers.CharField(read_only=True)
|
|
||||||
processed = serializers.BooleanField(read_only=True)
|
|
||||||
promotion_amount = serializers.IntegerField(read_only=True, allow_null=True)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminPlanSummarySerializer(serializers.ModelSerializer):
|
|
||||||
class Meta:
|
|
||||||
model = Plan
|
|
||||||
fields = ("uuid", "title", "processor")
|
|
||||||
|
|
||||||
|
|
||||||
class AdminPromotionSerializer(serializers.ModelSerializer):
|
|
||||||
"""Every Promotion row, i.e. every promotion received by a user."""
|
|
||||||
user = serializers.UUIDField(source='user_uuid', read_only=True)
|
|
||||||
plan = AdminPlanSummarySerializer(read_only=True)
|
|
||||||
promotion_type = serializers.SerializerMethodField()
|
|
||||||
event_label = serializers.SerializerMethodField()
|
|
||||||
state_display = serializers.CharField(source='get_state_display', read_only=True)
|
|
||||||
reward_amount = serializers.IntegerField(source='promotion_amount', read_only=True)
|
|
||||||
date = serializers.DateTimeField(source='created_at', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = (
|
|
||||||
"uuid",
|
|
||||||
"user",
|
|
||||||
"plan",
|
|
||||||
"promotion_type",
|
|
||||||
"event_label",
|
|
||||||
"base_amount",
|
|
||||||
"reward_amount",
|
|
||||||
"state",
|
|
||||||
"state_display",
|
|
||||||
"date",
|
|
||||||
"updated_at",
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_promotion_type(self, obj):
|
|
||||||
return obj.plan.processor if obj.plan_id else None
|
|
||||||
|
|
||||||
def get_event_label(self, obj):
|
|
||||||
return obj.event.label if obj.event_id else None
|
|
||||||
|
|
||||||
|
|
||||||
class AdminReferralSerializer(serializers.ModelSerializer):
|
|
||||||
"""
|
|
||||||
Referral activity, derived from Promotion rows on plans whose processor is
|
|
||||||
'referral'. There is no dedicated referral model and no referral_code field
|
|
||||||
in this codebase today (see docs/adminpanel_technical.md, "Known limitations").
|
|
||||||
|
|
||||||
In the recipient DSL a referral plan's Recipient resolves to
|
|
||||||
"->event:referral", so Promotion.user_uuid is the referrer being paid
|
|
||||||
(invited_by) -- not the person who triggered the event. The invited user
|
|
||||||
only exists as free-form JSON on the triggering Event (event.data['user']).
|
|
||||||
"""
|
|
||||||
invited_by = serializers.UUIDField(source='user_uuid', read_only=True)
|
|
||||||
invited_user = serializers.SerializerMethodField()
|
|
||||||
plan = AdminPlanSummarySerializer(read_only=True)
|
|
||||||
event_label = serializers.SerializerMethodField()
|
|
||||||
reward_amount = serializers.IntegerField(source='promotion_amount', read_only=True)
|
|
||||||
state_display = serializers.CharField(source='get_state_display', read_only=True)
|
|
||||||
date = serializers.DateTimeField(source='created_at', read_only=True)
|
|
||||||
|
|
||||||
class Meta:
|
|
||||||
model = Promotion
|
|
||||||
fields = (
|
|
||||||
"uuid",
|
|
||||||
"invited_user",
|
|
||||||
"invited_by",
|
|
||||||
"plan",
|
|
||||||
"event_label",
|
|
||||||
"reward_amount",
|
|
||||||
"state",
|
|
||||||
"state_display",
|
|
||||||
"date",
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_invited_user(self, obj):
|
|
||||||
if obj.event_id and obj.event.data:
|
|
||||||
return obj.event.data.get('user')
|
|
||||||
return None
|
|
||||||
|
|
||||||
def get_event_label(self, obj):
|
|
||||||
return obj.event.label if obj.event_id else None
|
|
||||||
|
|
||||||
|
|
||||||
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)
|
|
||||||
25
apps/promotions/serializers/__init__.py
Normal file
25
apps/promotions/serializers/__init__.py
Normal file
|
|
@ -0,0 +1,25 @@
|
||||||
|
from .common import (
|
||||||
|
EventSerializer,
|
||||||
|
PromotionSerializer,
|
||||||
|
PlanSerializer,
|
||||||
|
PlanPromotSerializer,
|
||||||
|
PromoteSerializer,
|
||||||
|
UserRecipientSerializer,
|
||||||
|
PromotionStatusSerializer,
|
||||||
|
UserPlanSerializer,
|
||||||
|
)
|
||||||
|
from .admin import AdminPlanSummarySerializer, AdminPromotionSerializer, AdminReferralSerializer
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'EventSerializer',
|
||||||
|
'PromotionSerializer',
|
||||||
|
'PlanSerializer',
|
||||||
|
'PlanPromotSerializer',
|
||||||
|
'PromoteSerializer',
|
||||||
|
'UserRecipientSerializer',
|
||||||
|
'PromotionStatusSerializer',
|
||||||
|
'UserPlanSerializer',
|
||||||
|
'AdminPlanSummarySerializer',
|
||||||
|
'AdminPromotionSerializer',
|
||||||
|
'AdminReferralSerializer',
|
||||||
|
]
|
||||||
8
apps/promotions/serializers/admin/__init__.py
Normal file
8
apps/promotions/serializers/admin/__init__.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
from .promotion import AdminPlanSummarySerializer, AdminPromotionSerializer
|
||||||
|
from .referral import AdminReferralSerializer
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'AdminPlanSummarySerializer',
|
||||||
|
'AdminPromotionSerializer',
|
||||||
|
'AdminReferralSerializer',
|
||||||
|
]
|
||||||
42
apps/promotions/serializers/admin/promotion.py
Normal file
42
apps/promotions/serializers/admin/promotion.py
Normal file
|
|
@ -0,0 +1,42 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.promotions.models import Promotion, Plan
|
||||||
|
|
||||||
|
|
||||||
|
class AdminPlanSummarySerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Plan
|
||||||
|
fields = ("uuid", "title", "processor")
|
||||||
|
|
||||||
|
|
||||||
|
class AdminPromotionSerializer(serializers.ModelSerializer):
|
||||||
|
"""Every Promotion row, i.e. every promotion received by a user."""
|
||||||
|
user = serializers.UUIDField(source='user_uuid', read_only=True)
|
||||||
|
plan = AdminPlanSummarySerializer(read_only=True)
|
||||||
|
promotion_type = serializers.SerializerMethodField()
|
||||||
|
event_label = serializers.SerializerMethodField()
|
||||||
|
state_display = serializers.CharField(source='get_state_display', read_only=True)
|
||||||
|
reward_amount = serializers.IntegerField(source='promotion_amount', read_only=True)
|
||||||
|
date = serializers.DateTimeField(source='created_at', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Promotion
|
||||||
|
fields = (
|
||||||
|
"uuid",
|
||||||
|
"user",
|
||||||
|
"plan",
|
||||||
|
"promotion_type",
|
||||||
|
"event_label",
|
||||||
|
"base_amount",
|
||||||
|
"reward_amount",
|
||||||
|
"state",
|
||||||
|
"state_display",
|
||||||
|
"date",
|
||||||
|
"updated_at",
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_promotion_type(self, obj):
|
||||||
|
return obj.plan.processor if obj.plan_id else None
|
||||||
|
|
||||||
|
def get_event_label(self, obj):
|
||||||
|
return obj.event.label if obj.event_id else None
|
||||||
46
apps/promotions/serializers/admin/referral.py
Normal file
46
apps/promotions/serializers/admin/referral.py
Normal file
|
|
@ -0,0 +1,46 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.promotions.models import Promotion
|
||||||
|
from .promotion import AdminPlanSummarySerializer
|
||||||
|
|
||||||
|
|
||||||
|
class AdminReferralSerializer(serializers.ModelSerializer):
|
||||||
|
"""
|
||||||
|
Referral activity, derived from Promotion rows on plans whose processor is
|
||||||
|
'referral'. There is no dedicated referral model and no referral_code field
|
||||||
|
in this codebase today (see docs/adminpanel_technical.md, "Known limitations").
|
||||||
|
|
||||||
|
In the recipient DSL a referral plan's Recipient resolves to
|
||||||
|
"->event:referral", so Promotion.user_uuid is the referrer being paid
|
||||||
|
(invited_by) -- not the person who triggered the event. The invited user
|
||||||
|
only exists as free-form JSON on the triggering Event (event.data['user']).
|
||||||
|
"""
|
||||||
|
invited_by = serializers.UUIDField(source='user_uuid', read_only=True)
|
||||||
|
invited_user = serializers.SerializerMethodField()
|
||||||
|
plan = AdminPlanSummarySerializer(read_only=True)
|
||||||
|
event_label = serializers.SerializerMethodField()
|
||||||
|
reward_amount = serializers.IntegerField(source='promotion_amount', read_only=True)
|
||||||
|
state_display = serializers.CharField(source='get_state_display', read_only=True)
|
||||||
|
date = serializers.DateTimeField(source='created_at', read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Promotion
|
||||||
|
fields = (
|
||||||
|
"uuid",
|
||||||
|
"invited_user",
|
||||||
|
"invited_by",
|
||||||
|
"plan",
|
||||||
|
"event_label",
|
||||||
|
"reward_amount",
|
||||||
|
"state",
|
||||||
|
"state_display",
|
||||||
|
"date",
|
||||||
|
)
|
||||||
|
|
||||||
|
def get_invited_user(self, obj):
|
||||||
|
if obj.event_id and obj.event.data:
|
||||||
|
return obj.event.data.get('user')
|
||||||
|
return None
|
||||||
|
|
||||||
|
def get_event_label(self, obj):
|
||||||
|
return obj.event.label if obj.event_id else None
|
||||||
107
apps/promotions/serializers/common.py
Normal file
107
apps/promotions/serializers/common.py
Normal file
|
|
@ -0,0 +1,107 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from apps.promotions.models import Promotion, Plan, Event, Recipient
|
||||||
|
|
||||||
|
|
||||||
|
class EventSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
fields = (
|
||||||
|
"label",
|
||||||
|
"data",
|
||||||
|
"user",
|
||||||
|
"application",
|
||||||
|
)
|
||||||
|
read_only_fields = ('user', 'application')
|
||||||
|
|
||||||
|
|
||||||
|
class PromotionSerializer(serializers.ModelSerializer):
|
||||||
|
# base_amount = serializers.IntegerField(required=True)
|
||||||
|
# promotion_amount = serializers.IntegerField(read_only=True)
|
||||||
|
event = EventSerializer(read_only=True)
|
||||||
|
user = serializers.UUIDField(source='user_uuid')
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Promotion
|
||||||
|
fields = (
|
||||||
|
"uuid",
|
||||||
|
"event",
|
||||||
|
"promotion_amount",
|
||||||
|
"state",
|
||||||
|
"user",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class PlanSerializer(serializers.ModelSerializer):
|
||||||
|
base_amount = serializers.IntegerField(required=True)
|
||||||
|
promotion_amount = serializers.IntegerField(read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Plan
|
||||||
|
fields = ("title",
|
||||||
|
"description",
|
||||||
|
"base_amount",
|
||||||
|
"application",
|
||||||
|
"promotion_amount"
|
||||||
|
)
|
||||||
|
read_only_fields = ('application', "promotion_amount", "title", "description")
|
||||||
|
|
||||||
|
# def get_promotion_amount(self, obj):
|
||||||
|
# user = self.context['request'].user
|
||||||
|
# return obj.calculate_promotion(user)
|
||||||
|
|
||||||
|
|
||||||
|
class PlanPromotSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Promotion
|
||||||
|
fields = (
|
||||||
|
"user",
|
||||||
|
"application",
|
||||||
|
)
|
||||||
|
read_only_fields = ('user', 'application')
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
class PromoteSerializer(serializers.ModelSerializer):
|
||||||
|
label = serializers.CharField(write_only=True)
|
||||||
|
data = serializers.JSONField(write_only=True)
|
||||||
|
|
||||||
|
promotions = PromotionSerializer(many=True, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Promotion
|
||||||
|
fields = (
|
||||||
|
"promotions",
|
||||||
|
"label",
|
||||||
|
"data",
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class UserRecipientSerializer(serializers.ModelSerializer):
|
||||||
|
class Meta:
|
||||||
|
model = Recipient
|
||||||
|
fields = ['label',
|
||||||
|
"base_amount_field"]
|
||||||
|
|
||||||
|
|
||||||
|
class PromotionStatusSerializer(serializers.Serializer):
|
||||||
|
event_label = serializers.CharField(read_only=True)
|
||||||
|
processed = serializers.BooleanField(read_only=True)
|
||||||
|
promotion_amount = serializers.IntegerField(read_only=True, allow_null=True)
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
6
apps/promotions/urls/__init__.py
Normal file
6
apps/promotions/urls/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
from .router import router
|
||||||
|
from . import admin_urls
|
||||||
|
|
||||||
|
app_name = 'promotions-admin'
|
||||||
|
|
||||||
|
urlpatterns = router.urls + admin_urls.urlpatterns
|
||||||
8
apps/promotions/urls/admin_urls.py
Normal file
8
apps/promotions/urls/admin_urls.py
Normal file
|
|
@ -0,0 +1,8 @@
|
||||||
|
from apps.promotions.views import AdminPromotionViewSet, AdminReferralViewSet
|
||||||
|
|
||||||
|
from .router import router
|
||||||
|
|
||||||
|
router.register('promotions', AdminPromotionViewSet, basename='admin-promotions')
|
||||||
|
router.register('referrals', AdminReferralViewSet, basename='admin-referrals')
|
||||||
|
|
||||||
|
urlpatterns = []
|
||||||
3
apps/promotions/urls/router.py
Normal file
3
apps/promotions/urls/router.py
Normal file
|
|
@ -0,0 +1,3 @@
|
||||||
|
from rest_framework.routers import DefaultRouter
|
||||||
|
|
||||||
|
router = DefaultRouter()
|
||||||
|
|
@ -1,12 +0,0 @@
|
||||||
from django.urls import path
|
|
||||||
|
|
||||||
from . import views_admin
|
|
||||||
|
|
||||||
app_name = 'promotions-admin'
|
|
||||||
|
|
||||||
urlpatterns = [
|
|
||||||
path('promotions/', views_admin.AdminPromotionListApiView.as_view(), name='promotion-list'),
|
|
||||||
path('promotions/<uuid:uuid>/', views_admin.AdminPromotionDetailApiView.as_view(), name='promotion-detail'),
|
|
||||||
path('referrals/', views_admin.AdminReferralListApiView.as_view(), name='referral-list'),
|
|
||||||
path('referrals/<uuid:uuid>/', views_admin.AdminReferralDetailApiView.as_view(), name='referral-detail'),
|
|
||||||
]
|
|
||||||
6
apps/promotions/views/__init__.py
Normal file
6
apps/promotions/views/__init__.py
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
from .admin import AdminPromotionViewSet, AdminReferralViewSet
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'AdminPromotionViewSet',
|
||||||
|
'AdminReferralViewSet',
|
||||||
|
]
|
||||||
7
apps/promotions/views/admin/__init__.py
Normal file
7
apps/promotions/views/admin/__init__.py
Normal file
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .promotion import AdminPromotionViewSet
|
||||||
|
from .referral import AdminReferralViewSet
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
'AdminPromotionViewSet',
|
||||||
|
'AdminReferralViewSet',
|
||||||
|
]
|
||||||
26
apps/promotions/views/admin/promotion.py
Normal file
26
apps/promotions/views/admin/promotion.py
Normal file
|
|
@ -0,0 +1,26 @@
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from rest_framework import mixins
|
||||||
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
|
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
||||||
|
from apps.promotions.filters import AdminPromotionFilter
|
||||||
|
from apps.promotions.models import Promotion
|
||||||
|
from apps.promotions.serializers import AdminPromotionSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class AdminPromotionViewSet(
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
|
GenericViewSet
|
||||||
|
):
|
||||||
|
"""Read-only: every Promotion received, per user, with type/amount/date."""
|
||||||
|
queryset = Promotion.objects.select_related('plan', 'event').order_by('-created_at')
|
||||||
|
serializer_class = AdminPromotionSerializer
|
||||||
|
lookup_field = 'uuid'
|
||||||
|
filter_backends = (DjangoFilterBackend,)
|
||||||
|
filterset_class = AdminPromotionFilter
|
||||||
|
|
||||||
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
||||||
|
required_alternate_scopes = {
|
||||||
|
"GET": [["admin.promotions:retrieve"]],
|
||||||
|
}
|
||||||
35
apps/promotions/views/admin/referral.py
Normal file
35
apps/promotions/views/admin/referral.py
Normal file
|
|
@ -0,0 +1,35 @@
|
||||||
|
from django_filters.rest_framework import DjangoFilterBackend
|
||||||
|
from rest_framework import mixins
|
||||||
|
from rest_framework.viewsets import GenericViewSet
|
||||||
|
|
||||||
|
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
||||||
|
from apps.promotions.filters import AdminReferralFilter
|
||||||
|
from apps.promotions.handlers import ProcessorTypeChoices
|
||||||
|
from apps.promotions.models import Promotion
|
||||||
|
from apps.promotions.serializers import AdminReferralSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class AdminReferralViewSet(
|
||||||
|
mixins.ListModelMixin,
|
||||||
|
mixins.RetrieveModelMixin,
|
||||||
|
GenericViewSet
|
||||||
|
):
|
||||||
|
"""
|
||||||
|
Read-only: referral activity. Scoped to Promotion rows on plans whose
|
||||||
|
processor == 'referral'. No dedicated Referral model / referral_code
|
||||||
|
field exists in this codebase; see docs/adminpanel_technical.md.
|
||||||
|
"""
|
||||||
|
serializer_class = AdminReferralSerializer
|
||||||
|
lookup_field = 'uuid'
|
||||||
|
filter_backends = (DjangoFilterBackend,)
|
||||||
|
filterset_class = AdminReferralFilter
|
||||||
|
|
||||||
|
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
||||||
|
required_alternate_scopes = {
|
||||||
|
"GET": [["admin.referrals:retrieve"]],
|
||||||
|
}
|
||||||
|
|
||||||
|
def get_queryset(self):
|
||||||
|
return Promotion.objects.select_related('plan', 'event').filter(
|
||||||
|
plan__processor=ProcessorTypeChoices.REFERRAL
|
||||||
|
).order_by('-created_at')
|
||||||
|
|
@ -1,62 +0,0 @@
|
||||||
from django_filters.rest_framework import DjangoFilterBackend
|
|
||||||
from rest_framework.generics import ListAPIView, RetrieveAPIView
|
|
||||||
|
|
||||||
from apps.gooyal_oauth2.rest_framework import IsAuthenticatedOrTokenMatchesOASRequirements
|
|
||||||
from .filters_admin import AdminPromotionFilter, AdminReferralFilter
|
|
||||||
from .handlers import ProcessorTypeChoices
|
|
||||||
from .models import Promotion
|
|
||||||
from .serializers import AdminPromotionSerializer, AdminReferralSerializer
|
|
||||||
|
|
||||||
ADMIN_PROMOTION_QUERYSET = Promotion.objects.select_related('plan', 'event').order_by('-created_at')
|
|
||||||
|
|
||||||
|
|
||||||
class AdminPromotionListApiView(ListAPIView):
|
|
||||||
"""Read-only: every Promotion received, per user, with type/amount/date."""
|
|
||||||
queryset = ADMIN_PROMOTION_QUERYSET
|
|
||||||
serializer_class = AdminPromotionSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
||||||
required_alternate_scopes = {
|
|
||||||
"GET": [["admin.promotions:retrieve"]],
|
|
||||||
}
|
|
||||||
filter_backends = [DjangoFilterBackend]
|
|
||||||
filterset_class = AdminPromotionFilter
|
|
||||||
|
|
||||||
|
|
||||||
class AdminPromotionDetailApiView(RetrieveAPIView):
|
|
||||||
queryset = ADMIN_PROMOTION_QUERYSET
|
|
||||||
serializer_class = AdminPromotionSerializer
|
|
||||||
lookup_field = 'uuid'
|
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
||||||
required_alternate_scopes = {
|
|
||||||
"GET": [["admin.promotions:retrieve"]],
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
class AdminReferralListApiView(ListAPIView):
|
|
||||||
"""
|
|
||||||
Read-only: referral activity. Scoped to Promotion rows on plans whose
|
|
||||||
processor == 'referral'. No dedicated Referral model / referral_code
|
|
||||||
field exists in this codebase; see docs/adminpanel_technical.md.
|
|
||||||
"""
|
|
||||||
serializer_class = AdminReferralSerializer
|
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
||||||
required_alternate_scopes = {
|
|
||||||
"GET": [["admin.referrals:retrieve"]],
|
|
||||||
}
|
|
||||||
filter_backends = [DjangoFilterBackend]
|
|
||||||
filterset_class = AdminReferralFilter
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return ADMIN_PROMOTION_QUERYSET.filter(plan__processor=ProcessorTypeChoices.REFERRAL)
|
|
||||||
|
|
||||||
|
|
||||||
class AdminReferralDetailApiView(RetrieveAPIView):
|
|
||||||
serializer_class = AdminReferralSerializer
|
|
||||||
lookup_field = 'uuid'
|
|
||||||
permission_classes = [IsAuthenticatedOrTokenMatchesOASRequirements]
|
|
||||||
required_alternate_scopes = {
|
|
||||||
"GET": [["admin.referrals:retrieve"]],
|
|
||||||
}
|
|
||||||
|
|
||||||
def get_queryset(self):
|
|
||||||
return ADMIN_PROMOTION_QUERYSET.filter(plan__processor=ProcessorTypeChoices.REFERRAL)
|
|
||||||
Loading…
Add table
Reference in a new issue