mirror of
https://github.com/more-tech4-magnum-opus/backend.git
synced 2024-11-21 19:16:33 +03:00
added event crud
This commit is contained in:
parent
dada351290
commit
7172920c07
|
@ -1,6 +1,17 @@
|
||||||
from rest_framework import permissions
|
from rest_framework import permissions
|
||||||
|
|
||||||
|
|
||||||
|
class IsWorker(permissions.BasePermission):
|
||||||
|
"""
|
||||||
|
Checks if request user is worker(not hr or admin)
|
||||||
|
"""
|
||||||
|
|
||||||
|
def has_permission(self, request, view):
|
||||||
|
if request.method in permissions.SAFE_METHODS:
|
||||||
|
return True
|
||||||
|
return not request.user.is_manager
|
||||||
|
|
||||||
|
|
||||||
class IsManager(permissions.BasePermission):
|
class IsManager(permissions.BasePermission):
|
||||||
"""
|
"""
|
||||||
Checks if request user is an admin or hr
|
Checks if request user is an admin or hr
|
||||||
|
@ -14,7 +25,7 @@ class IsManager(permissions.BasePermission):
|
||||||
|
|
||||||
class IsAdmin(permissions.BasePermission):
|
class IsAdmin(permissions.BasePermission):
|
||||||
"""
|
"""
|
||||||
Checks if request user is an admin or hr
|
Checks if request user is an admin
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def has_permission(self, request, view):
|
def has_permission(self, request, view):
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
from django.urls import path, include
|
from django.urls import path, include
|
||||||
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
from rest_framework_simplejwt.views import TokenObtainPairView, TokenRefreshView
|
||||||
|
|
||||||
|
from events.api.views import ListCreateEventApi, RetireUpdateDeleteEventApi
|
||||||
from marketplace.api.views import ListCreateProductApi, RetireUpdateDestroyProductApi
|
from marketplace.api.views import ListCreateProductApi, RetireUpdateDestroyProductApi
|
||||||
from users.api.views import (
|
from users.api.views import (
|
||||||
ListCreateUserApi,
|
ListCreateUserApi,
|
||||||
|
@ -23,6 +24,19 @@ urlpatterns = [
|
||||||
]
|
]
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
path(
|
||||||
|
"events/",
|
||||||
|
include(
|
||||||
|
[
|
||||||
|
path("", ListCreateEventApi.as_view(), name="list_create_event"),
|
||||||
|
path(
|
||||||
|
"<str:slug>",
|
||||||
|
RetireUpdateDeleteEventApi.as_view(),
|
||||||
|
name="get_update_delete_event",
|
||||||
|
),
|
||||||
|
]
|
||||||
|
),
|
||||||
|
),
|
||||||
path(
|
path(
|
||||||
"marketplace/",
|
"marketplace/",
|
||||||
include(
|
include(
|
||||||
|
|
|
@ -39,6 +39,7 @@ REST_FRAMEWORK = {
|
||||||
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
"rest_framework_simplejwt.authentication.JWTAuthentication",
|
||||||
),
|
),
|
||||||
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.AllowAny",),
|
"DEFAULT_PERMISSION_CLASSES": ("rest_framework.permissions.AllowAny",),
|
||||||
|
"DATETIME_FORMAT": "%Y-%m-%dT%H:%M:%S.%fZ",
|
||||||
}
|
}
|
||||||
|
|
||||||
# STATIC
|
# STATIC
|
||||||
|
|
0
app/events/api/__init__.py
Normal file
0
app/events/api/__init__.py
Normal file
32
app/events/api/serializers.py
Normal file
32
app/events/api/serializers.py
Normal file
|
@ -0,0 +1,32 @@
|
||||||
|
from rest_framework import serializers
|
||||||
|
|
||||||
|
from events.models import Event
|
||||||
|
from users.api.serializers import UserSerializer
|
||||||
|
|
||||||
|
|
||||||
|
class EventSerializer(serializers.ModelSerializer):
|
||||||
|
creator = UserSerializer(many=False, read_only=True)
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
model = Event
|
||||||
|
fields = [
|
||||||
|
"name",
|
||||||
|
"about",
|
||||||
|
"slug",
|
||||||
|
"creator",
|
||||||
|
"starts",
|
||||||
|
"image",
|
||||||
|
"planning",
|
||||||
|
"attended",
|
||||||
|
]
|
||||||
|
extra_kwargs = {
|
||||||
|
"slug": {"read_only": True},
|
||||||
|
"creator": {"read_only": True},
|
||||||
|
"planning": {"read_only": True},
|
||||||
|
"attended": {"read_only": True},
|
||||||
|
}
|
||||||
|
|
||||||
|
def create(self, validated_data):
|
||||||
|
return Event.objects.create(
|
||||||
|
**validated_data, creator=self.context["request"].user
|
||||||
|
)
|
34
app/events/api/views.py
Normal file
34
app/events/api/views.py
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
from datetime import datetime
|
||||||
|
|
||||||
|
import pytz
|
||||||
|
from rest_framework import generics
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
from rest_framework.parsers import FormParser, MultiPartParser
|
||||||
|
from rest_framework.permissions import IsAuthenticated
|
||||||
|
|
||||||
|
from common.permissions import IsManager
|
||||||
|
from events.api.serializers import EventSerializer
|
||||||
|
from events.models import Event
|
||||||
|
|
||||||
|
|
||||||
|
class ListCreateEventApi(generics.ListCreateAPIView):
|
||||||
|
serializer_class = EventSerializer
|
||||||
|
parser_classes = [FormParser, MultiPartParser]
|
||||||
|
permission_classes = [IsAuthenticated, IsManager]
|
||||||
|
queryset = Event.objects.filter(
|
||||||
|
starts__gte=datetime.now(pytz.timezone("Europe/Moscow"))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
class RetireUpdateDeleteEventApi(generics.RetrieveUpdateDestroyAPIView):
|
||||||
|
def get_object(self):
|
||||||
|
event = get_object_or_404(
|
||||||
|
Event,
|
||||||
|
slug=self.request.parser_context["kwargs"]["slug"],
|
||||||
|
)
|
||||||
|
return event
|
||||||
|
|
||||||
|
serializer_class = EventSerializer
|
||||||
|
parser_classes = [FormParser, MultiPartParser]
|
||||||
|
permission_classes = [IsAuthenticated, IsManager]
|
||||||
|
queryset = Event.objects.all()
|
|
@ -2,5 +2,8 @@ from django.apps import AppConfig
|
||||||
|
|
||||||
|
|
||||||
class EventsConfig(AppConfig):
|
class EventsConfig(AppConfig):
|
||||||
default_auto_field = 'django.db.models.BigAutoField'
|
default_auto_field = "django.db.models.BigAutoField"
|
||||||
name = 'events'
|
name = "events"
|
||||||
|
|
||||||
|
def ready(self):
|
||||||
|
import events.signals
|
||||||
|
|
45
app/events/migrations/0001_initial.py
Normal file
45
app/events/migrations/0001_initial.py
Normal file
|
@ -0,0 +1,45 @@
|
||||||
|
# Generated by Django 4.0.8 on 2022-10-08 15:44
|
||||||
|
|
||||||
|
from django.conf import settings
|
||||||
|
from django.db import migrations, models
|
||||||
|
import django.db.models.deletion
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
|
||||||
|
initial = True
|
||||||
|
|
||||||
|
dependencies = [
|
||||||
|
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='Event',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('name', models.CharField(max_length=100)),
|
||||||
|
('slug', models.SlugField(max_length=8)),
|
||||||
|
('about', models.TextField(blank=True)),
|
||||||
|
('starts', models.DateTimeField()),
|
||||||
|
('image', models.ImageField(blank=True, upload_to='uploads/')),
|
||||||
|
('image_cropped', models.ImageField(blank=True, upload_to='cropped/')),
|
||||||
|
('planning', models.IntegerField(default=0)),
|
||||||
|
('attended', models.IntegerField(default=0)),
|
||||||
|
('creator', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events_created', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
options={
|
||||||
|
'ordering': ['-starts'],
|
||||||
|
},
|
||||||
|
),
|
||||||
|
migrations.CreateModel(
|
||||||
|
name='EventAttendance',
|
||||||
|
fields=[
|
||||||
|
('id', models.BigAutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||||
|
('token', models.CharField(max_length=128, unique=True)),
|
||||||
|
('attended', models.BooleanField(default=False)),
|
||||||
|
('event', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='people', to='events.event')),
|
||||||
|
('worker', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='events', to=settings.AUTH_USER_MODEL)),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
]
|
|
@ -1,3 +1,36 @@
|
||||||
from django.db import models
|
from django.db import models
|
||||||
|
|
||||||
# Create your models here.
|
from users.models import User
|
||||||
|
|
||||||
|
|
||||||
|
class Event(models.Model):
|
||||||
|
name = models.CharField(max_length=100)
|
||||||
|
slug = models.SlugField(max_length=8)
|
||||||
|
about = models.TextField(blank=True)
|
||||||
|
|
||||||
|
creator = models.ForeignKey(
|
||||||
|
User, related_name="events_created", on_delete=models.CASCADE
|
||||||
|
)
|
||||||
|
starts = models.DateTimeField(blank=False)
|
||||||
|
|
||||||
|
image = models.ImageField(upload_to="uploads/", blank=True)
|
||||||
|
image_cropped = models.ImageField(upload_to="cropped/", blank=True)
|
||||||
|
|
||||||
|
planning = models.IntegerField(default=0)
|
||||||
|
attended = models.IntegerField(default=0)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return self.name
|
||||||
|
|
||||||
|
class Meta:
|
||||||
|
ordering = ["-starts"]
|
||||||
|
|
||||||
|
|
||||||
|
class EventAttendance(models.Model):
|
||||||
|
event = models.ForeignKey(Event, related_name="people", on_delete=models.CASCADE)
|
||||||
|
worker = models.ForeignKey(User, related_name="events", on_delete=models.CASCADE)
|
||||||
|
token = models.CharField(blank=False, unique=True, max_length=128)
|
||||||
|
attended = models.BooleanField(default=False)
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
return f"{self.worker.name} attendance on {self.event.name}"
|
||||||
|
|
13
app/events/services.py
Normal file
13
app/events/services.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from rest_framework.generics import get_object_or_404
|
||||||
|
|
||||||
|
from events.models import EventAttendance
|
||||||
|
|
||||||
|
|
||||||
|
def submit_attendance(token: str):
|
||||||
|
attendance = get_object_or_404(EventAttendance, token=token)
|
||||||
|
if not attendance.attended:
|
||||||
|
attendance.attended = True
|
||||||
|
attendance.save()
|
||||||
|
|
||||||
|
attendance.event.attended += 1
|
||||||
|
attendance.event.save()
|
41
app/events/signals.py
Normal file
41
app/events/signals.py
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
from django.core.files import File
|
||||||
|
from django.db.models.signals import pre_save, post_delete, post_save
|
||||||
|
from django.dispatch import receiver
|
||||||
|
|
||||||
|
from utils.file import crop_image
|
||||||
|
from utils.generators import generate_charset
|
||||||
|
from .models import EventAttendance, Event
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(pre_save, sender=EventAttendance)
|
||||||
|
def create_attendance(sender, instance, **kwargs):
|
||||||
|
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"])
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_save, sender=Event)
|
||||||
|
def process_event(sender, instance, created, **kwargs):
|
||||||
|
if created:
|
||||||
|
slug = generate_charset(5)
|
||||||
|
while Event.objects.filter(slug=slug).exists():
|
||||||
|
slug = generate_charset(5)
|
||||||
|
instance.slug = slug
|
||||||
|
instance.save(update_fields=["slug"])
|
||||||
|
|
||||||
|
if instance.image and kwargs["update_fields"] is None:
|
||||||
|
instance.image_cropped = File(
|
||||||
|
crop_image(instance.image.path, cut_to=(250, 250)),
|
||||||
|
name=instance.image.path.split(".")[0].split("/")[-1] + ".png",
|
||||||
|
)
|
||||||
|
instance.save(update_fields=["image_cropped"])
|
||||||
|
|
||||||
|
|
||||||
|
@receiver(post_delete, sender=EventAttendance)
|
||||||
|
def delete_attendance(sender, instance, **kwargs):
|
||||||
|
instance.event.planning -= 1
|
||||||
|
instance.event.save(update_fileds=["planning"])
|
|
@ -1,3 +0,0 @@
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
|
Loading…
Reference in New Issue
Block a user