mirror of
https://github.com/more-tech4-magnum-opus/backend.git
synced 2024-11-22 03:26:34 +03:00
added full event logic, fixed clan creation, minor changes
This commit is contained in:
parent
8beee17e31
commit
12f81dbf3f
|
@ -1,18 +1,26 @@
|
|||
from django.urls import path, include
|
||||
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||
|
||||
from events.api.views import ListCreateEventApi, RetireUpdateDeleteEventApi
|
||||
from marketplace.api.views import ListCreateProductApi, RetireUpdateDestroyProductApi
|
||||
from events.api.views import (
|
||||
ListCreateEventApi,
|
||||
RetrieveUpdateDeleteEventApi,
|
||||
ListPlannedEvents,
|
||||
RetrieveSubmitDeleteEventAttendance,
|
||||
ListAttendedWorkersApi,
|
||||
SubmitWorkerAttendedEvent,
|
||||
)
|
||||
from marketplace.api.views import ListCreateProductApi, RetrieveUpdateDestroyProductApi
|
||||
from users.api.views import (
|
||||
ListCreateUserApi,
|
||||
RetireUpdateDeleteUserApi,
|
||||
RetrieveUpdateDeleteUserApi,
|
||||
ListCreateDepartmentApi,
|
||||
RetireUpdateDeleteDepartmentApi,
|
||||
RetrieveUpdateDeleteDepartmentApi,
|
||||
ListCreateStreamApi,
|
||||
RetireUpdateDeleteStreamApi,
|
||||
RetrieveUpdateDeleteStreamApi,
|
||||
ListCreateCommandApi,
|
||||
RetireUpdateDeleteCommandApi,
|
||||
RetrieveUpdateDeleteCommandApi,
|
||||
CreateSeasonApi,
|
||||
ListClansApiView,
|
||||
)
|
||||
|
||||
urlpatterns = [
|
||||
|
@ -32,9 +40,29 @@ urlpatterns = [
|
|||
path("", ListCreateEventApi.as_view(), name="list_create_event"),
|
||||
path(
|
||||
"<str:slug>",
|
||||
RetireUpdateDeleteEventApi.as_view(),
|
||||
RetrieveUpdateDeleteEventApi.as_view(),
|
||||
name="get_update_delete_event",
|
||||
),
|
||||
path(
|
||||
"attendance/",
|
||||
ListPlannedEvents.as_view(),
|
||||
name="list_event_attendance",
|
||||
),
|
||||
path(
|
||||
"attendance/<str:slug>/list/",
|
||||
ListAttendedWorkersApi.as_view(),
|
||||
name="list_event_attendance",
|
||||
),
|
||||
path(
|
||||
"attendance/<str:slug>/submit/",
|
||||
SubmitWorkerAttendedEvent.as_view(),
|
||||
name="submit_event_attendance",
|
||||
),
|
||||
path(
|
||||
"attendance/<str:slug>",
|
||||
RetrieveSubmitDeleteEventAttendance.as_view(),
|
||||
name="get_submit_delete_event_attendance",
|
||||
),
|
||||
]
|
||||
),
|
||||
),
|
||||
|
@ -49,7 +77,7 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"product/<str:slug>",
|
||||
RetireUpdateDestroyProductApi.as_view(),
|
||||
RetrieveUpdateDestroyProductApi.as_view(),
|
||||
name="get_update_destroy_product",
|
||||
),
|
||||
]
|
||||
|
@ -62,7 +90,7 @@ urlpatterns = [
|
|||
path("", ListCreateUserApi.as_view(), name="list_create_user"),
|
||||
path(
|
||||
"<str:username>",
|
||||
RetireUpdateDeleteUserApi.as_view(),
|
||||
RetrieveUpdateDeleteUserApi.as_view(),
|
||||
name="get_update_delete_user",
|
||||
),
|
||||
path(
|
||||
|
@ -77,7 +105,7 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"department/<int:pk>",
|
||||
RetireUpdateDeleteDepartmentApi.as_view(),
|
||||
RetrieveUpdateDeleteDepartmentApi.as_view(),
|
||||
name="get_update_delete_department",
|
||||
),
|
||||
path(
|
||||
|
@ -87,7 +115,7 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"stream/<int:pk>",
|
||||
RetireUpdateDeleteStreamApi.as_view(),
|
||||
RetrieveUpdateDeleteStreamApi.as_view(),
|
||||
name="get_update_delete_stream",
|
||||
),
|
||||
path(
|
||||
|
@ -97,7 +125,7 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"command/<int:pk>",
|
||||
RetireUpdateDeleteCommandApi.as_view(),
|
||||
RetrieveUpdateDeleteCommandApi.as_view(),
|
||||
name="get_update_delete_command",
|
||||
),
|
||||
]
|
||||
|
@ -105,6 +133,11 @@ urlpatterns = [
|
|||
),
|
||||
path(
|
||||
"season/",
|
||||
include([path("", CreateSeasonApi.as_view(), name="create new season")]),
|
||||
include(
|
||||
[
|
||||
path("", CreateSeasonApi.as_view(), name="create new season"),
|
||||
path("clans/", ListClansApiView.as_view()),
|
||||
]
|
||||
),
|
||||
),
|
||||
]
|
||||
|
|
|
@ -62,7 +62,7 @@ DJANGO_APPS = [
|
|||
]
|
||||
THIRD_PARTY_APPS = ["rest_framework", "corsheaders", "django_celery_beat", "drf_yasg"]
|
||||
|
||||
LOCAL_APPS = ["users", "marketplace", "events"]
|
||||
LOCAL_APPS = ["users", "marketplace", "events", "blockchain"]
|
||||
# https://docs.djangoproject.com/en/dev/ref/settings/#installed-apps
|
||||
INSTALLED_APPS = DJANGO_APPS + THIRD_PARTY_APPS + LOCAL_APPS
|
||||
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from rest_framework import serializers
|
||||
from rest_framework.generics import get_object_or_404
|
||||
|
||||
from events.models import Event
|
||||
from events.models import Event, EventAttendance
|
||||
from users.api.serializers import UserSerializer
|
||||
from users.models import User
|
||||
|
||||
|
||||
class EventSerializer(serializers.ModelSerializer):
|
||||
|
@ -30,3 +32,45 @@ class EventSerializer(serializers.ModelSerializer):
|
|||
return Event.objects.create(
|
||||
**validated_data, creator=self.context["request"].user
|
||||
)
|
||||
|
||||
|
||||
class EventAttendanceSerializer(serializers.ModelSerializer):
|
||||
class Meta:
|
||||
model = EventAttendance
|
||||
fields = ["id", "event_slug", "worker_username", "attended"]
|
||||
extra_kwargs = {
|
||||
"id": {"read_only": True},
|
||||
"event_slug": {"read_only": True},
|
||||
"worker_username": {"read_only": True},
|
||||
"attended": {"read_only": True},
|
||||
}
|
||||
|
||||
def create(self, validated_data):
|
||||
return EventAttendance.objects.get_or_create(
|
||||
worker=self.context["request"].user,
|
||||
event=get_object_or_404(
|
||||
Event, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||
),
|
||||
)[0]
|
||||
|
||||
|
||||
class SubmitUserAttendedSerializer(serializers.Serializer):
|
||||
username = serializers.CharField(max_length=200)
|
||||
|
||||
def create(self, validated_data):
|
||||
event = get_object_or_404(
|
||||
Event, slug=self.context["request"].parser_context["kwargs"]["slug"]
|
||||
)
|
||||
ea = EventAttendance.objects.get_or_create(
|
||||
event=event,
|
||||
worker=get_object_or_404(User, username=validated_data["username"]),
|
||||
)[0]
|
||||
if not ea.attended:
|
||||
ea.attended = True
|
||||
ea.save()
|
||||
ea.event.attended += 1
|
||||
ea.event.save()
|
||||
return ea
|
||||
|
||||
def update(self, instance, validated_data):
|
||||
pass
|
||||
|
|
|
@ -2,13 +2,19 @@ from datetime import datetime
|
|||
|
||||
import pytz
|
||||
from rest_framework import generics
|
||||
from rest_framework.exceptions import NotFound
|
||||
from rest_framework.generics import get_object_or_404
|
||||
from rest_framework.parsers import FormParser, MultiPartParser
|
||||
from rest_framework.permissions import IsAuthenticated
|
||||
from rest_framework.views import APIView
|
||||
|
||||
from common.permissions import IsManager
|
||||
from events.api.serializers import EventSerializer
|
||||
from events.models import Event
|
||||
from common.permissions import IsManager, IsWorker
|
||||
from events.api.serializers import (
|
||||
EventSerializer,
|
||||
EventAttendanceSerializer,
|
||||
SubmitUserAttendedSerializer,
|
||||
)
|
||||
from events.models import Event, EventAttendance
|
||||
|
||||
|
||||
class ListCreateEventApi(generics.ListCreateAPIView):
|
||||
|
@ -20,7 +26,7 @@ class ListCreateEventApi(generics.ListCreateAPIView):
|
|||
)
|
||||
|
||||
|
||||
class RetireUpdateDeleteEventApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class RetrieveUpdateDeleteEventApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
def get_object(self):
|
||||
event = get_object_or_404(
|
||||
Event,
|
||||
|
@ -32,3 +38,51 @@ class RetireUpdateDeleteEventApi(generics.RetrieveUpdateDestroyAPIView):
|
|||
parser_classes = [FormParser, MultiPartParser]
|
||||
permission_classes = [IsAuthenticated, IsManager]
|
||||
queryset = Event.objects.all()
|
||||
|
||||
|
||||
class RetrieveSubmitDeleteEventAttendance(
|
||||
generics.CreateAPIView, generics.RetrieveDestroyAPIView
|
||||
):
|
||||
"""Gets/Submits/Deletes that user is planing to go on event. Only works for worker"""
|
||||
|
||||
def get_object(self):
|
||||
event = get_object_or_404(
|
||||
Event,
|
||||
slug=self.request.parser_context["kwargs"]["slug"],
|
||||
)
|
||||
if EventAttendance.objects.filter(
|
||||
event=event, worker=self.request.user
|
||||
).exists():
|
||||
return EventAttendance.objects.get(event=event, worker=self.request.user)
|
||||
raise NotFound
|
||||
|
||||
serializer_class = EventAttendanceSerializer
|
||||
permission_classes = [IsAuthenticated, IsWorker]
|
||||
|
||||
|
||||
class ListPlannedEvents(generics.ListAPIView):
|
||||
"""Lists events that worker is planning to attend. Only works for worker"""
|
||||
|
||||
def get_queryset(self):
|
||||
return self.request.user.events.filter(
|
||||
attended=False,
|
||||
event__starts__gte=datetime.now(pytz.timezone("Europe/Moscow")),
|
||||
)
|
||||
|
||||
serializer_class = EventAttendanceSerializer
|
||||
permission_classes = [IsAuthenticated, IsWorker]
|
||||
|
||||
|
||||
class ListAttendedWorkersApi(generics.ListAPIView):
|
||||
def get_queryset(self):
|
||||
return EventAttendance.objects.filter(
|
||||
event__slug=self.request.parser_context["kwargs"]["slug"]
|
||||
)
|
||||
|
||||
serializer_class = EventAttendanceSerializer
|
||||
permission_classes = [IsAuthenticated, IsManager]
|
||||
|
||||
|
||||
class SubmitWorkerAttendedEvent(generics.CreateAPIView):
|
||||
serializer_class = SubmitUserAttendedSerializer
|
||||
permission_classes = [IsAuthenticated, IsManager]
|
||||
|
|
|
@ -32,5 +32,20 @@ class EventAttendance(models.Model):
|
|||
token = models.CharField(blank=False, unique=True, max_length=128)
|
||||
attended = models.BooleanField(default=False)
|
||||
|
||||
@property
|
||||
def event_slug(self):
|
||||
return self.event.slug
|
||||
|
||||
@property
|
||||
def worker_username(self):
|
||||
return self.worker.username
|
||||
|
||||
def username(self):
|
||||
return self.worker_username
|
||||
|
||||
def __str__(self):
|
||||
return f"{self.worker.name} attendance on {self.event.name}"
|
||||
|
||||
class Meta:
|
||||
ordering = ["event__starts"]
|
||||
unique_together = ["event", "worker"]
|
||||
|
|
|
@ -7,15 +7,16 @@ from utils.generators import generate_charset
|
|||
from .models import EventAttendance, Event
|
||||
|
||||
|
||||
@receiver(pre_save, sender=EventAttendance)
|
||||
def create_attendance(sender, instance, **kwargs):
|
||||
@receiver(post_save, sender=EventAttendance)
|
||||
def create_attendance(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
token = generate_charset(25)
|
||||
while EventAttendance.objects.filter(token=token).exists():
|
||||
token = generate_charset(25)
|
||||
instance.token = token
|
||||
|
||||
instance.event.planning += 1
|
||||
instance.event.save(update_fileds=["planning"])
|
||||
instance.event.save(update_fields=["planning", "token"])
|
||||
|
||||
|
||||
@receiver(post_save, sender=Event)
|
||||
|
@ -38,4 +39,4 @@ def process_event(sender, instance, created, **kwargs):
|
|||
@receiver(post_delete, sender=EventAttendance)
|
||||
def delete_attendance(sender, instance, **kwargs):
|
||||
instance.event.planning -= 1
|
||||
instance.event.save(update_fileds=["planning"])
|
||||
instance.event.save(update_fields=["planning"])
|
||||
|
|
|
@ -15,7 +15,7 @@ class ListCreateProductApi(generics.ListCreateAPIView):
|
|||
queryset = Product.objects.all()
|
||||
|
||||
|
||||
class RetireUpdateDestroyProductApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class RetrieveUpdateDestroyProductApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
serializer_class = ProductSerializer
|
||||
parser_classes = [FormParser, MultiPartParser]
|
||||
permission_classes = [IsAuthenticated, IsManager]
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from rest_framework import serializers
|
||||
from ..services import create_season
|
||||
from users.models import User
|
||||
from users.models import User, Clan
|
||||
from users.models import User, Department, Stream, Command
|
||||
|
||||
|
||||
|
@ -18,10 +18,12 @@ class UserSerializer(serializers.ModelSerializer):
|
|||
"wallet_public_key",
|
||||
"command",
|
||||
"department",
|
||||
"clan_name",
|
||||
]
|
||||
extra_kwargs = {
|
||||
"password": {"write_only": True},
|
||||
"wallet_public_key": {"read_only": True},
|
||||
"clan_name": {"read_only": True},
|
||||
"department": {"read_only": True},
|
||||
}
|
||||
|
||||
|
@ -34,9 +36,10 @@ class UserSerializer(serializers.ModelSerializer):
|
|||
|
||||
class CreateSeasonSerializer(serializers.Serializer):
|
||||
created = serializers.BooleanField(read_only=True)
|
||||
|
||||
def create(self, *args, **kwargs):
|
||||
create_season()
|
||||
return {'created': True}
|
||||
return {"created": True}
|
||||
|
||||
|
||||
class CommandSerializer(serializers.ModelSerializer):
|
||||
|
@ -75,3 +78,11 @@ class DepartmentSerializer(serializers.ModelSerializer):
|
|||
"id": {"read_only": True},
|
||||
"streams": {"read_only": True},
|
||||
}
|
||||
|
||||
|
||||
class ClanSerializer(serializers.ModelSerializer):
|
||||
users = UserSerializer(many=True)
|
||||
|
||||
class Meta:
|
||||
model = Clan
|
||||
fields = ["name", "users"]
|
||||
|
|
|
@ -3,14 +3,15 @@ from rest_framework.generics import get_object_or_404
|
|||
from rest_framework.permissions import IsAuthenticated
|
||||
|
||||
from common.permissions import IsAdmin
|
||||
from users.api.serializers import CreateSeasonSerializer
|
||||
from users.api.serializers import (
|
||||
UserSerializer,
|
||||
DepartmentSerializer,
|
||||
StreamSerializer,
|
||||
CommandSerializer,
|
||||
CreateSeasonSerializer,
|
||||
ClanSerializer,
|
||||
)
|
||||
from users.models import User, Department, Stream, Command
|
||||
from users.models import User, Department, Stream, Command, Clan
|
||||
|
||||
|
||||
class ListCreateUserApi(generics.ListCreateAPIView):
|
||||
|
@ -24,7 +25,7 @@ class CreateSeasonApi(generics.CreateAPIView):
|
|||
# permission_classes = [IsAuthenticated, IsAdmin]
|
||||
|
||||
|
||||
class RetireUpdateDeleteUserApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class RetrieveUpdateDeleteUserApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
def get_object(self):
|
||||
user = get_object_or_404(
|
||||
User,
|
||||
|
@ -43,7 +44,7 @@ class ListCreateDepartmentApi(generics.ListCreateAPIView):
|
|||
queryset = Department.objects.all()
|
||||
|
||||
|
||||
class RetireUpdateDeleteDepartmentApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
class RetrieveUpdateDeleteDepartmentApi(generics.RetrieveUpdateDestroyAPIView):
|
||||
lookup_field = "pk"
|
||||
serializer_class = DepartmentSerializer
|
||||
permission_classes = [IsAuthenticated, IsAdmin]
|
||||
|
@ -55,7 +56,7 @@ class ListCreateStreamApi(ListCreateDepartmentApi):
|
|||
queryset = Stream.objects.all()
|
||||
|
||||
|
||||
class RetireUpdateDeleteStreamApi(RetireUpdateDeleteDepartmentApi):
|
||||
class RetrieveUpdateDeleteStreamApi(RetrieveUpdateDeleteDepartmentApi):
|
||||
serializer_class = StreamSerializer
|
||||
queryset = Stream.objects.all()
|
||||
|
||||
|
@ -65,6 +66,12 @@ class ListCreateCommandApi(ListCreateDepartmentApi):
|
|||
queryset = Command.objects.all()
|
||||
|
||||
|
||||
class RetireUpdateDeleteCommandApi(RetireUpdateDeleteDepartmentApi):
|
||||
class RetrieveUpdateDeleteCommandApi(RetrieveUpdateDeleteDepartmentApi):
|
||||
serializer_class = CommandSerializer
|
||||
queryset = Command.objects.all()
|
||||
|
||||
|
||||
class ListClansApiView(generics.ListAPIView):
|
||||
serializer_class = ClanSerializer
|
||||
queryset = Clan.objects.all()
|
||||
permission_classes = [IsAuthenticated, IsAdmin]
|
||||
|
|
|
@ -22,7 +22,7 @@ class User(AbstractUser):
|
|||
type = models.CharField(
|
||||
max_length=6, choices=WorkerType.choices, default=WorkerType.WORKER
|
||||
)
|
||||
clan = models.ForeignKey("users.Clan", on_delete=models.SET_NULL, null=True)
|
||||
clan = models.ForeignKey("users.Clan", related_name="users", on_delete=models.SET_NULL, null=True)
|
||||
command = models.ForeignKey(
|
||||
"users.Command", related_name="workers", on_delete=models.CASCADE
|
||||
)
|
||||
|
@ -47,6 +47,10 @@ class User(AbstractUser):
|
|||
def department(self):
|
||||
return self.command.stream.department.name
|
||||
|
||||
@property
|
||||
def clan_name(self):
|
||||
return self.clan.name
|
||||
|
||||
class Meta:
|
||||
ordering = ["-id"]
|
||||
|
||||
|
|
|
@ -12,10 +12,10 @@ def end_season():
|
|||
mx_value = -1
|
||||
mx_clan = None
|
||||
for clan in Clan.objects.all():
|
||||
if sum(map(lambda user: user.respect, clan.user_set.all())) > mx_value:
|
||||
mx_value = sum(map(lambda user: user.respect, clan.user_set.all()))
|
||||
if sum(map(lambda user: user.respect, clan.users.all())) > mx_value:
|
||||
mx_value = sum(map(lambda user: user.respect, clan.users.all()))
|
||||
mx_clan = clan
|
||||
for user in mx_clan.user_set.all():
|
||||
for user in mx_clan.users.all():
|
||||
transfer_rubbles(
|
||||
settings.MAIN_WALLET,
|
||||
user.wallet_public_key,
|
||||
|
@ -25,7 +25,7 @@ def end_season():
|
|||
|
||||
|
||||
def create_chat(clan: Clan):
|
||||
user_list = list(map(lambda user: user.telegram, clan.user_set.all()))
|
||||
user_list = list(map(lambda user: user.telegram, clan.users.all()))
|
||||
if len(user_list):
|
||||
r.post(
|
||||
f"{settings.TELEGRAM_API}/create-chat",
|
||||
|
@ -38,15 +38,13 @@ def create_season():
|
|||
if len(Clan.objects.all()):
|
||||
end_season()
|
||||
|
||||
users = list(User.objects.all())
|
||||
users = list(User.objects.filter(type=User.WorkerType.WORKER))
|
||||
shuffle(users)
|
||||
clan = None
|
||||
for index, user in enumerate(users):
|
||||
if (index % 10 == 0) or (index == len(users) - 1):
|
||||
if clan is not None:
|
||||
create_chat(clan)
|
||||
if index % 5 == 0:
|
||||
clan = Clan.objects.create()
|
||||
user.clan = clan
|
||||
user.save()
|
||||
if len(users) % 10 != 0:
|
||||
for clan in Clan.objects.all():
|
||||
create_chat(clan)
|
||||
|
|
|
@ -5,15 +5,13 @@ from users.models import User
|
|||
from utils.blockchain import create_wallet
|
||||
|
||||
|
||||
@receiver(pre_save, sender=User)
|
||||
def create_user(sender, instance, **kwargs):
|
||||
wallet = create_wallet()
|
||||
instance.wallet_public_key = wallet.publicKey
|
||||
instance.wallet_private_key = wallet.privateKey
|
||||
|
||||
|
||||
@receiver(post_save, sender=User)
|
||||
def process_user(sender, instance, created, **kwargs):
|
||||
if created:
|
||||
instance.set_password(instance.password)
|
||||
|
||||
wallet = create_wallet()
|
||||
|
||||
instance.wallet_public_key = wallet.publicKey
|
||||
instance.wallet_private_key = wallet.privateKey
|
||||
instance.save()
|
||||
|
|
Loading…
Reference in New Issue
Block a user