Browse Source

feat: add setting, transaction

master
alireza 1 year ago
parent
commit
9a61b74777
  1. 26
      apps/account/manager.py
  2. 18
      apps/account/migrations/0005_user_city.py
  3. 1
      apps/account/models/user.py
  4. 2
      apps/account/serializers/user.py
  5. 2
      apps/chat/admin.py
  6. 2
      apps/course/admin/participant.py
  7. 3
      apps/course/models/participant.py
  8. 1
      apps/course/serializers/__init__.py
  9. 17
      apps/course/serializers/participant.py
  10. 1
      apps/course/urls.py
  11. 40
      apps/course/views/participant.py
  12. 0
      apps/transaction/__init__.py
  13. 37
      apps/transaction/admin.py
  14. 6
      apps/transaction/apps.py
  15. 44
      apps/transaction/migrations/0001_initial.py
  16. 0
      apps/transaction/migrations/__init__.py
  17. 50
      apps/transaction/models.py
  18. 44
      apps/transaction/serializers.py
  19. 3
      apps/transaction/tests.py
  20. 13
      apps/transaction/urls.py
  21. 77
      apps/transaction/views.py
  22. 3
      config/settings/base.py
  23. 3
      config/urls.py
  24. 166
      dynamic_preferences/dynamic_preferences_registry.py
  25. 17
      dynamic_preferences/serializers.py
  26. 20
      dynamic_preferences/urls.py
  27. 59
      dynamic_preferences/views.py

26
apps/account/manager.py

@ -1,5 +1,6 @@
from django.contrib.auth.models import BaseUserManager from django.contrib.auth.models import BaseUserManager
from django.contrib.auth.models import Group
from django.db.models import Manager from django.db.models import Manager
@ -40,23 +41,16 @@ class UserManager(BaseUserManager):
return user return user
def change_user_type(self, new_user_type):
# حذف گروه‌های فعلی
old_group_name = f"{self.user_type.capitalize()} Group"
old_group = Group.objects.filter(name=old_group_name).first()
if old_group:
self.groups.remove(old_group)
def change_user_type(self, user, new_user_type):
group_name = f"{new_user_type.capitalize()} Group"
if user.user_type != new_user_type and not user.groups.filter(name=group_name).exists():
# تغییر نوع کاربر
self.user_type = new_user_type
# افزودن گروه جدید
new_group_name = f"{new_user_type.capitalize()} Group"
new_group, _ = Group.objects.get_or_create(name=new_group_name)
self.groups.add(new_group)
# ذخیره تغییرات
self.save()
user.user_type = new_user_type
new_group, _ = Group.objects.get_or_create(name=group_name)
user.groups.add(new_group)
user.save()
return user
return None

18
apps/account/migrations/0005_user_city.py

@ -0,0 +1,18 @@
# Generated by Django 3.2.4 on 2024-11-30 23:53
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
('account', '0004_user_skill'),
]
operations = [
migrations.AddField(
model_name='user',
name='city',
field=models.CharField(blank=True, max_length=255, null=True, verbose_name='City'),
),
]

1
apps/account/models/user.py

@ -42,6 +42,7 @@ class User(AbstractUser):
verbose_name="User Type", verbose_name="User Type",
help_text="Type of the user." help_text="Type of the user."
) )
city = models.CharField(verbose_name=_('City'), max_length=255, null=True, blank=True)
device_id = models.CharField(verbose_name=_('device id'), max_length=255, null=True, blank=True) device_id = models.CharField(verbose_name=_('device id'), max_length=255, null=True, blank=True)
fcm = models.CharField(max_length=512, null=True, blank=True) fcm = models.CharField(max_length=512, null=True, blank=True)
date_joined = models.DateTimeField(auto_now_add=True, verbose_name="Date Joined", help_text="The date and time the user registered.") date_joined = models.DateTimeField(auto_now_add=True, verbose_name="Date Joined", help_text="The date and time the user registered.")

2
apps/account/serializers/user.py

@ -15,7 +15,7 @@ class UserProfileSerializer(serializers.ModelSerializer):
fullname = serializers.CharField(required=False) fullname = serializers.CharField(required=False)
class Meta: class Meta:
model = User model = User
fields = ['id', 'fullname', 'avatar', 'email', 'phone_number', 'password', 'info', 'skill']
fields = ['id', 'fullname', 'avatar', 'email', 'phone_number', 'password', 'info', 'skill', 'city']
read_only_fields = ['email', 'info'] read_only_fields = ['email', 'info']
# def validate_email(self, value): # def validate_email(self, value):

2
apps/chat/admin.py

@ -15,7 +15,7 @@ class MessageReadStatusAdmin(admin.ModelAdmin):
@admin.register(RoomMessage) @admin.register(RoomMessage)
class RoomMessageAdmin(admin.ModelAdmin): class RoomMessageAdmin(admin.ModelAdmin):
list_display = ( list_display = (
'name', 'room_type', 'course', 'initiator', 'recipient', 'created_at',
'name', 'room_type', 'course', 'initiator', 'recipient', 'created_at', 'unread_messages_count'
) )
list_filter = ('room_type', 'created_at', 'updated_at', 'course') list_filter = ('room_type', 'created_at', 'updated_at', 'course')
search_fields = ('name', 'description', 'course__title', 'initiator__username', 'recipient__username') search_fields = ('name', 'description', 'course__title', 'initiator__username', 'recipient__username')

2
apps/course/admin/participant.py

@ -7,7 +7,7 @@ from apps.account.models import StudentUser, User
@admin.register(Participant) @admin.register(Participant)
class ParticipantAdmin(admin.ModelAdmin): class ParticipantAdmin(admin.ModelAdmin):
list_display = ('student', 'course', 'joined_date')
list_display = ('student', 'course', 'joined_date', 'unread_messages_count')
search_fields = ('student__fullname', 'student__email', 'course__title') search_fields = ('student__fullname', 'student__email', 'course__title')
list_filter = ('course', 'joined_date') list_filter = ('course', 'joined_date')
ordering = ('-joined_date',) ordering = ('-joined_date',)

3
apps/course/models/participant.py

@ -2,7 +2,7 @@
from django.db import models from django.db import models
from apps.account.models import StudentUser
from apps.account.models import StudentUser, User
from apps.course.models import Course from apps.course.models import Course
@ -22,4 +22,3 @@ class Participant(models.Model):
class Meta: class Meta:
unique_together = ('student', 'course') unique_together = ('student', 'course')

1
apps/course/serializers/__init__.py

@ -1,2 +1,3 @@
from .course import * from .course import *
from .lesson import * from .lesson import *
from .participant import *

17
apps/course/serializers/participant.py

@ -0,0 +1,17 @@
from rest_framework import serializers
from apps.course.models import Lesson, Participant, LessonCompletion
from apps.account.models import StudentUser, User
class ParticipantSerializer(serializers.ModelSerializer):
email = serializers.EmailField(required=True)
gender = serializers.ChoiceField(choices=User.GenderChoices.choices, required=True)
class Meta:
model = StudentUser
fields = ['fullname' , 'phone_number', 'gender', 'email', 'birthdate']

1
apps/course/urls.py

@ -15,5 +15,6 @@ urlpatterns = [
path('<slug:slug>/lessons/', views.LessonListView.as_view(), name='course-lesson-list'), path('<slug:slug>/lessons/', views.LessonListView.as_view(), name='course-lesson-list'),
path('<slug:slug>/participants/', views.CourseParticipantsView.as_view(), name='course-participant-list'), path('<slug:slug>/participants/', views.CourseParticipantsView.as_view(), name='course-participant-list'),
# path('<slug:slug>/participant/join/', views.ParticipantCreateView.as_view(), name='course-participant-join'),
] ]

40
apps/course/views/participant.py

@ -1,17 +1,20 @@
from rest_framework.generics import ListAPIView
from rest_framework import generics
from rest_framework.exceptions import NotFound from rest_framework.exceptions import NotFound
from drf_yasg.utils import swagger_auto_schema from drf_yasg.utils import swagger_auto_schema
from drf_yasg import openapi from drf_yasg import openapi
from rest_framework.permissions import IsAuthenticated
from apps.account.models import StudentUser from apps.account.models import StudentUser
from apps.course.models import Participant, Course from apps.course.models import Participant, Course
from apps.course.serializers import ParticipantSerializer
from apps.account.serializers import UserProfileSerializer from apps.account.serializers import UserProfileSerializer
from apps.course.doc import * from apps.course.doc import *
from utils.exceptions import AppAPIException
class CourseParticipantsView(ListAPIView):
class CourseParticipantsView(generics.ListAPIView):
serializer_class = UserProfileSerializer serializer_class = UserProfileSerializer
@swagger_auto_schema( @swagger_auto_schema(
@ -22,6 +25,37 @@ class CourseParticipantsView(ListAPIView):
try: try:
course = Course.objects.get(slug=course_slug) course = Course.objects.get(slug=course_slug)
except Course.DoesNotExist: except Course.DoesNotExist:
raise NotFound("Course not found")
raise AppAPIException({'message': "Course not found"}) # Handle course not found
return StudentUser.objects.filter(participated_courses__course=course) return StudentUser.objects.filter(participated_courses__course=course)
# class ParticipantCreateView(generics.CreateAPIView):
# queryset = StudentUser.objects.all()
# serializer_class = ParticipantSerializer
# permission_classes = [IsAuthenticated]
# def create(self, request, *args, **kwargs):
# user = request.user
# course_slug = self.kwargs.get('slug') # Get the slug from the URL
# try:
# course = Course.objects.get(slug=slug) # Retrieve the Course object
# except Course.DoesNotExist:
# raise AppAPIException({'message': "Course not found"}) # Handle course not found
# if request.data.get('email') != request.user:
# raise AppAPIException({'message': "The email must be for the requesting user"})
# if user.user_type != User.UserType.STUDENT:
# user.change_user_type(User.UserType.STUDENT)
# participant, created = Participant.objects.get_or_create(
# student=user,
# course=course
# )
# serializer = self.get_serializer(participant)
# return Response(serializer.data, status=status.HTTP_201_CREATED)

0
apps/transaction/__init__.py

37
apps/transaction/admin.py

@ -0,0 +1,37 @@
from django.contrib import admin
from apps.transaction.models import TransactionParticipant, ParticipantInfo
from django.utils.translation import gettext_lazy as _
class ParticipantInfoInline(admin.StackedInline):
model = ParticipantInfo
extra = 1
fields = ['fullname', 'email', 'phone_number', 'gender', 'birthdate']
# readonly_fields = ['email', 'phone_number']
classes = ['collapse']
@admin.register(TransactionParticipant)
class TransactionParticipantAdmin(admin.ModelAdmin):
list_display = ('user', 'course', 'is_paid', 'price', 'created_at', 'updated_at')
list_filter = ('is_paid', 'course', 'created_at')
search_fields = ('user__email', 'course__title')
readonly_fields = ['user', 'course', 'price', 'created_at', 'updated_at']
inlines = [ParticipantInfoInline]
ordering = ('-created_at',)
list_filter = ('is_paid', 'course', 'created_at')
fieldsets = (
(None, {
'fields': ('user', 'course', 'is_paid', 'price')
}),
(_('Timestamps'), {
'fields': ('created_at', 'updated_at'),
'classes': ('collapse',)
}),
)

6
apps/transaction/apps.py

@ -0,0 +1,6 @@
from django.apps import AppConfig
class TransactionConfig(AppConfig):
default_auto_field = 'django.db.models.BigAutoField'
name = 'apps.transaction'

44
apps/transaction/migrations/0001_initial.py

@ -0,0 +1,44 @@
# Generated by Django 3.2.4 on 2024-11-30 22:25
from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion
import phonenumber_field.modelfields
import utils.validators
class Migration(migrations.Migration):
initial = True
dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
('course', '0005_participant_unread_messages_count'),
]
operations = [
migrations.CreateModel(
name='TransactionParticipant',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('is_paid', models.BooleanField(default=False, help_text='Indicates whether the payment has been completed or not', verbose_name='Payment Status')),
('price', models.DecimalField(decimal_places=2, default=0.0, max_digits=10, verbose_name='Transaction Price')),
('created_at', models.DateTimeField(auto_now_add=True, verbose_name='Created at')),
('updated_at', models.DateTimeField(auto_now=True, verbose_name='Updated at')),
('course', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='course_transactions', to='course.course')),
('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='transactions', to=settings.AUTH_USER_MODEL)),
],
),
migrations.CreateModel(
name='ParticipantInfo',
fields=[
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('fullname', models.CharField(help_text='Enter the full name of the user.', max_length=255, verbose_name='Full Name')),
('email', models.EmailField(help_text="Enter the user's email address.", max_length=254, unique=True, verbose_name='Email Address')),
('phone_number', phonenumber_field.modelfields.PhoneNumberField(blank=True, max_length=128, null=True, region=None, unique=True, validators=[utils.validators.validate_possible_number], verbose_name='phone')),
('gender', models.CharField(blank=True, choices=[('male', 'Male'), ('female', 'Female')], help_text="Select the user's gender.", max_length=20, null=True, verbose_name='Gender')),
('birthdate', models.DateField(blank=True, null=True, verbose_name='birthdate')),
('transaction_participant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='participant_infos', to='transaction.transactionparticipant', verbose_name='Transaction Participant')),
],
),
]

0
apps/transaction/migrations/__init__.py

50
apps/transaction/models.py

@ -0,0 +1,50 @@
from django.db import models
from django.utils.translation import gettext_lazy as _
from apps.account.models import StudentUser, User
from apps.course.models import Course
from phonenumber_field.modelfields import PhoneNumberField
from utils.validators import validate_possible_number
class TransactionParticipant(models.Model):
user = models.ForeignKey(User, on_delete=models.CASCADE, related_name='transactions')
course = models.ForeignKey(Course, on_delete=models.CASCADE, related_name='course_transactions')
is_paid = models.BooleanField(default=False, verbose_name='Payment Status', help_text='Indicates whether the payment has been completed or not')
price = models.DecimalField(max_digits=10, decimal_places=2, default=0.00, verbose_name='Transaction Price')
created_at = models.DateTimeField(auto_now_add=True, verbose_name=_("Created at"))
updated_at = models.DateTimeField(auto_now=True, verbose_name=_("Updated at"))
class ParticipantInfo(models.Model):
class GenderChoices(models.TextChoices):
MALE = 'male', 'Male'
FEMALE = 'female', 'Female'
transaction_participant = models.ForeignKey(
TransactionParticipant,
on_delete=models.CASCADE,
related_name='participant_infos',
verbose_name="Transaction Participant"
)
fullname = models.CharField(max_length=255, verbose_name="Full Name", help_text="Enter the full name of the user.")
email = models.EmailField(unique=True, verbose_name="Email Address", help_text="Enter the user's email address.")
phone_number = PhoneNumberField(unique=True, validators=[validate_possible_number], null=True, blank=True, verbose_name=_('phone'))
gender = models.CharField(
max_length=20, choices=GenderChoices.choices, null=True, blank=True, verbose_name=_('Gender'), help_text="Select the user's gender."
)
birthdate = models.DateField(verbose_name=_('birthdate'), null=True, blank=True)

44
apps/transaction/serializers.py

@ -0,0 +1,44 @@
from rest_framework import serializers
from apps.transaction.models import TransactionParticipant, ParticipantInfo
from apps.course.serializers import CourseDetailSerializer
class ParticipantInfoSerializer(serializers.ModelSerializer):
class Meta:
model = ParticipantInfo
fields = ['fullname', 'email', 'phone_number', 'gender', 'birthdate']
class TransactionParticipantSerializer(serializers.ModelSerializer):
participant_infos = ParticipantInfoSerializer(many=True)
class Meta:
model = TransactionParticipant
fields = ['participant_infos']
def create(self, validated_data):
participant_infos_data = validated_data.pop('participant_infos', [])
transaction_participant = TransactionParticipant.objects.create(**validated_data)
for participant_info_data in participant_infos_data:
ParticipantInfo.objects.create(transaction_participant=transaction_participant, **participant_info_data)
return transaction_participant
class TransactionListSerializer(serializers.ModelSerializer):
course = serializers.SerializerMethodField()
class Meta:
model = TransactionParticipant
fields = ['course', 'is_paid', 'price', 'created_at', 'updated_at']
def get_course(self, obj):
return CourseDetailSerializer(obj.course, context=self.context).data

3
apps/transaction/tests.py

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

13
apps/transaction/urls.py

@ -0,0 +1,13 @@
from django.urls import path
from . import views
urlpatterns = [
path('<slug:slug>/join/', views.TransactionParticipantCreateView.as_view(), name='transaction-participant-create'),
path('list/', views.TransactiontListView.as_view(), name='transaction-list'),
]

77
apps/transaction/views.py

@ -0,0 +1,77 @@
from rest_framework import generics, status
from rest_framework.permissions import IsAuthenticated
from rest_framework.response import Response
from apps.course.models import Participant, Course
from apps.transaction.models import TransactionParticipant
from apps.transaction.serializers import TransactionParticipantSerializer, TransactionListSerializer
from utils.exceptions import AppAPIException
from apps.account.models import User
class TransactionParticipantCreateView(generics.CreateAPIView):
queryset = TransactionParticipant.objects.all()
serializer_class = TransactionParticipantSerializer
permission_classes = [IsAuthenticated]
def create(self, request, *args, **kwargs):
user = request.user
course_slug = self.kwargs.get('slug') # Get the slug from the URL
try:
course = Course.objects.get(slug=course_slug) # Retrieve the Course object
except Course.DoesNotExist:
raise AppAPIException({'message': "Course not found"}) # Handle course not found
participant_infos = request.data.get('participant_infos', [])
print(f'1---> {participant_infos}')
print(f'2---> {len(participant_infos)}')
serializer = self.get_serializer(data=request.data)
serializer.is_valid(raise_exception=True)
if len(participant_infos) == 1 and (course.final_price == 0 or course.is_free):
participant = participant_infos[0]
if participant.get('email') != user.email:
raise AppAPIException({'message': "The email must be for the requesting user"})
if user.user_type != User.UserType.STUDENT:
user = User.objects.change_user_type(user, User.UserType.STUDENT)
participant, created = Participant.objects.get_or_create(
student=user,
course=course
)
return Response({
'message': 'Transaction Participant created successfully.',
'participant_id': participant.id,
'participant_infos': serializer.data['participant_infos']
}, status=status.HTTP_201_CREATED)
transaction_participant = serializer.save(user=user, course=course, price=course.final_price)
print(f'---> {type(transaction_participant)}/ {transaction_participant}')
return Response({
'message': 'Transaction Participant created successfully.',
'transaction_id': transaction_participant.id,
'participant_infos': serializer.data['participant_infos']
}, status=status.HTTP_201_CREATED)
class TransactiontListView(generics.ListAPIView):
queryset = TransactionParticipant.objects.all() # یا هر فیلتر که بخواهید اضافه کنید
serializer_class = TransactionListSerializer
permission_classes = [IsAuthenticated] # برای دسترسی کاربران احراز هویت شده
def get_queryset(self):
queryset = super().get_queryset()
queryset = queryset.filter(user=self.request.user)
return queryset

3
config/settings/base.py

@ -45,6 +45,9 @@ LOCAL_APPS = [
'apps.course.apps.CourseConfig', 'apps.course.apps.CourseConfig',
'apps.chat.apps.ChatConfig', 'apps.chat.apps.ChatConfig',
'apps.quiz.apps.QuizConfig', 'apps.quiz.apps.QuizConfig',
'apps.transaction.apps.TransactionConfig',
'dynamic_preferences',
] ]
THIRD_PARTY_APPS = [ THIRD_PARTY_APPS = [

3
config/urls.py

@ -37,6 +37,9 @@ api_patterns = [
path('account/', include('apps.account.urls')), path('account/', include('apps.account.urls')),
path('courses/', include('apps.course.urls')), path('courses/', include('apps.course.urls')),
path('quiz/', include('apps.quiz.urls')), path('quiz/', include('apps.quiz.urls')),
path('transaction/', include('apps.transaction.urls')),
path('settings/', include('dynamic_preferences.urls')),
path('upload-tmp-media/', UploadTmpMedia.as_view()), path('upload-tmp-media/', UploadTmpMedia.as_view()),
] ]

166
dynamic_preferences/dynamic_preferences_registry.py

@ -3,6 +3,7 @@ import json
from django import forms from django import forms
from limitless_dashboard.fields.tinyeditor import TinyWidget from limitless_dashboard.fields.tinyeditor import TinyWidget
# from limitless_dashboard.fields.summernote import
from dynamic_preferences.preferences import Section from dynamic_preferences.preferences import Section
from dynamic_preferences.registries import global_preferences_registry from dynamic_preferences.registries import global_preferences_registry
@ -13,3 +14,168 @@ from utils.json_editor_field import JsonEditorWidget
class EditorPreferences(LongStringPreference): class EditorPreferences(LongStringPreference):
widget = TinyWidget(attrs={'class': 'editor-field'}) widget = TinyWidget(attrs={'class': 'editor-field'})
@global_preferences_registry.register
class AboutUsConfig(EditorPreferences):
section = Section('aboutus', verbose_name='AboutUsConfig')
name = 'aboutus'
required = False
verbose_name = 'About Us'
default = ''
class JsonSerializer(BaseSerializer):
@classmethod
def serialize(cls, value, **kwargs):
return json.dumps(value, ensure_ascii=False)
@classmethod
def to_python(cls, value, **kwargs):
if isinstance(value, str) and len(value.strip()) > 0:
try:
return json.loads(value)
except json.JSONDecodeError as e:
try:
value_replaced = value.replace("'", '"')
return json.loads(value_replaced)
except json.JSONDecodeError as e2:
return {}
return value
get_fqa_courses_schema = {
'type': "array",
'format': 'table',
'title': ' ',
'items': {
'type': 'object',
'title': str('Questions about courses'),
'properties': {
'question': {'type': 'string', "format": "textarea", 'title': str('Question')},
'answer': {
'type': "string",
"format": "textarea",
'title': str('Answer')
}
}
}
}
class JsonFieldFAQCourse(BasePreferenceType):
field_class = forms.JSONField
serializer = JsonSerializer
widget = JsonEditorWidget(attrs={'schema': get_fqa_courses_schema})
@global_preferences_registry.register
class FAQCourseConfig(JsonFieldFAQCourse):
widget = JsonEditorWidget(attrs={'schema': get_fqa_courses_schema})
section = Section('FAQ_Course', verbose_name='Questions about courses')
name = 'FAQ_Course'
required = False
verbose_name = 'FAQ Course'
default = {}
get_fqa_general_schema = {
'type': "array",
'format': 'table',
'title': ' ',
'items': {
'type': 'object',
'title': str('Questions General'),
'properties': {
'question': {'type': 'string', "format": "textarea", 'title': str('Question')},
'answer': {
'type': "string",
"format": "textarea",
'title': str('Answer')
}
}
}
}
class JsonFieldFAQGeneral(BasePreferenceType):
field_class = forms.JSONField
serializer = JsonSerializer
widget = JsonEditorWidget(attrs={'schema': get_fqa_general_schema})
@global_preferences_registry.register
class FAQGeneralConfig(JsonFieldFAQGeneral):
widget = JsonEditorWidget(attrs={'schema': get_fqa_general_schema})
section = Section('FAQ_General', verbose_name='Questions General')
name = 'FAQ_General'
required = False
verbose_name = 'FAQ General'
default = {}
support_fields = {
"type": "object",
"format": "table",
"title": "",
"required_by_default": 1,
"required": ['telegram_number', "whatsapp_number"],
"properties": {
"telegram_number": {"type": "string", "title": "Telegram Number"},
"whatsapp_number": {"type": "string", "title": "Whatsapp Number"},
}
}
class JsonFieldSupport(BasePreferenceType):
field_class = forms.JSONField
serializer = JsonSerializer
widget = JsonEditorWidget(attrs={'schema': support_fields})
@global_preferences_registry.register
class SupportConfig(JsonFieldSupport):
section = Section('support', verbose_name='Support Detail')
name = 'support'
required = False
verbose_name = 'Support Detail'
default = {}
card_fields = {
"type": "object",
"format": "table",
"title": "",
"required_by_default": 1,
"required": ['card_number', "whatsapp_number"],
"properties": {
"card_number": {"type": "string", "title": "Card Number"},
"whatsapp_number": {"type": "string", "title": "Whatsapp Number"},
}
}
class JsonFieldCard(BasePreferenceType):
field_class = forms.JSONField
serializer = JsonSerializer
widget = JsonEditorWidget(attrs={'schema': card_fields})
@global_preferences_registry.register
class SupportConfig(JsonFieldCard):
section = Section('card', verbose_name='Card Detail')
name = 'card'
required = False
verbose_name = 'Card Detail'
default = {}

17
dynamic_preferences/serializers.py

@ -24,6 +24,23 @@ from django.utils.timezone import (
from six import string_types, text_type from six import string_types, text_type
from django.db.models.fields.files import FieldFile from django.db.models.fields.files import FieldFile
from rest_framework import serializers
class AboutUsSerializer(serializers.Serializer):
content = serializers.CharField(allow_blank=True)
class FAQItemSerializer(serializers.Serializer):
question = serializers.CharField()
answer = serializers.CharField()
class SupportSerializer(serializers.Serializer):
telegram_number = serializers.CharField()
whatsapp_number = serializers.CharField()
class CardSerializer(serializers.Serializer):
card_number = serializers.CharField()
whatsapp_number = serializers.CharField()
class UnsetValue(object): class UnsetValue(object):
pass pass

20
dynamic_preferences/urls.py

@ -7,10 +7,30 @@ from django.contrib.admin.views.decorators import staff_member_required
from . import views from . import views
from .registries import global_preferences_registry from .registries import global_preferences_registry
from .forms import GlobalPreferenceForm from .forms import GlobalPreferenceForm
from django.urls import path
from .views import (
AboutUsAPIView,
FAQCourseAPIView,
FAQGeneralAPIView,
SupportAPIView,
CardAPIView
)
app_name = "dynamic_preferences" app_name = "dynamic_preferences"
urlpatterns = [ urlpatterns = [
path('about-us/', AboutUsAPIView.as_view(), name='about-us-api'),
path('faq-course/', FAQCourseAPIView.as_view(), name='faq-course-api'),
path('faq-general/', FAQGeneralAPIView.as_view(), name='faq-general-api'),
path('support/', SupportAPIView.as_view(), name='support-api'),
path('card/', CardAPIView.as_view(), name='card-api'),
re_path( re_path(
r"^global/$", r"^global/$",
staff_member_required( staff_member_required(

59
dynamic_preferences/views.py

@ -1,6 +1,65 @@
from django.views.generic import TemplateView, FormView from django.views.generic import TemplateView, FormView
from django.http import Http404 from django.http import Http404
from .forms import preference_form_builder from .forms import preference_form_builder
from rest_framework.generics import GenericAPIView
from rest_framework.response import Response
from dynamic_preferences.registries import global_preferences_registry
from .serializers import (
AboutUsSerializer,
FAQItemSerializer,
SupportSerializer,
CardSerializer
)
class AboutUsAPIView(GenericAPIView):
serializer_class = AboutUsSerializer
def get(self, request, *args, **kwargs):
preferences = global_preferences_registry.manager()
about_us = preferences.get('aboutus__aboutus', '')
serializer = self.get_serializer(data={'content': about_us})
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
class FAQCourseAPIView(GenericAPIView):
serializer_class = FAQItemSerializer
def get(self, request, *args, **kwargs):
preferences = global_preferences_registry.manager()
faq_course = preferences.get('FAQ_Course__FAQ_Course', [])
serializer = self.get_serializer(data=faq_course, many=True)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
class FAQGeneralAPIView(GenericAPIView):
serializer_class = FAQItemSerializer
def get(self, request, *args, **kwargs):
preferences = global_preferences_registry.manager()
faq_general = preferences.get('FAQ_General__FAQ_General', [])
serializer = self.get_serializer(data=faq_general, many=True)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
class SupportAPIView(GenericAPIView):
serializer_class = SupportSerializer
def get(self, request, *args, **kwargs):
preferences = global_preferences_registry.manager()
support = preferences.get('support__support', {})
serializer = self.get_serializer(data=support)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
class CardAPIView(GenericAPIView):
serializer_class = CardSerializer
def get(self, request, *args, **kwargs):
preferences = global_preferences_registry.manager()
card = preferences.get('card__card', {})
serializer = self.get_serializer(data=card)
serializer.is_valid(raise_exception=True)
return Response(serializer.data)
"""Todo : remove these views and use only context processors""" """Todo : remove these views and use only context processors"""

Loading…
Cancel
Save