Skip to content

Commit

Permalink
Early april update (#789)
Browse files Browse the repository at this point in the history
* Feat(kontres)/add image to bookable item (#785)

* added optional image to bookable item model

* added update method in serializer to handle new images

* linting

* remove update method for images

* Feat(kontres)/add approved by (#786)

* added approved by field

* endpoint will now set approved by

* serializer will return full user object in approved_by_detail

* created test for approved by

* migration

* remove unnecessary code

* removed write-only field in approved-by context

* Create minutes for Codex (#787)

* init

* format

* Feat(minute)/viewset (#788)

* added richer reponse on post and put

* added to admin panel

* added filter for minute

---------

Co-authored-by: Erik Skjellevik <98759397+eriskjel@users.noreply.github.com>
  • Loading branch information
MadsNyl and eriskjel committed Apr 8, 2024
1 parent ef9e6b5 commit 3d0726e
Show file tree
Hide file tree
Showing 25 changed files with 525 additions and 3 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@

## Neste versjon

## Versjon 2023.04.08
-**Codex** Index brukere kan nå opprette dokumenter og møtereferater i Codex.

## Versjon 2023.03.11
- 🦟 **Vipps** Brukere som kommer fra venteliste vil nå få en payment countdown startet, slik at de blir kastet ut hvis de ikke betaler.
-**Venteliste** Brukere vil nå se sin reelle ventelisteplass som tar hensyn til prioriteringer.
Expand Down
7 changes: 7 additions & 0 deletions app/content/admin/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -251,3 +251,10 @@ def object_link(self, obj):

object_link.admin_order_field = "object_repr"
object_link.short_description = "object"


@admin.register(models.Minute)
class MinuteAdmin(admin.ModelAdmin):
list_display = ("title", "author", "created_at", "updated_at")
search_fields = ("title", "content", "author__user_id")
list_filter = ("author",)
5 changes: 5 additions & 0 deletions app/content/enums.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,8 @@ class CategoryEnum(ChoiceEnum):
KURS = "Kurs"
ANNET = "Annet"
FADDERUKA = "Fadderuka"


class MinuteTagEnum(models.TextChoices):
MINUTE = "Møtereferat"
DOCUMENT = "Dokument"
1 change: 1 addition & 0 deletions app/content/factories/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,4 @@
from app.content.factories.priority_pool_factory import PriorityPoolFactory
from app.content.factories.qr_code_factory import QRCodeFactory
from app.content.factories.logentry_factory import LogEntryFactory
from app.content.factories.minute_factory import MinuteFactory
14 changes: 14 additions & 0 deletions app/content/factories/minute_factory.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import factory
from factory.django import DjangoModelFactory

from app.content.factories.user_factory import UserFactory
from app.content.models.minute import Minute


class MinuteFactory(DjangoModelFactory):
class Meta:
model = Minute

title = factory.Faker("sentence", nb_words=4)
content = factory.Faker("text")
author = factory.SubFactory(UserFactory)
1 change: 1 addition & 0 deletions app/content/filters/__init__.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
from app.content.filters.cheatsheet import CheatsheetFilter
from app.content.filters.event import EventFilter
from app.content.filters.user import UserFilter
from app.content.filters.minute import MinuteFilter
15 changes: 15 additions & 0 deletions app/content/filters/minute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
from django_filters.rest_framework import FilterSet, OrderingFilter

from app.content.models import Minute


class MinuteFilter(FilterSet):
"""Filters minutes"""

ordering = OrderingFilter(
fields=("created_at", "updated_at", "title", "author", "tag")
)

class Meta:
model = Minute
fields = ["author", "title", "tag"]
47 changes: 47 additions & 0 deletions app/content/migrations/0059_minute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Generated by Django 4.2.5 on 2024-04-08 17:56

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
("content", "0058_merge_20231217_2155"),
]

operations = [
migrations.CreateModel(
name="Minute",
fields=[
(
"id",
models.AutoField(
auto_created=True,
primary_key=True,
serialize=False,
verbose_name="ID",
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
("title", models.CharField(max_length=200)),
("content", models.TextField(blank=True, default="")),
(
"author",
models.ForeignKey(
blank=True,
default=None,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="meeting_minutes",
to=settings.AUTH_USER_MODEL,
),
),
],
options={
"abstract": False,
},
),
]
22 changes: 22 additions & 0 deletions app/content/migrations/0060_minute_tag.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# Generated by Django 4.2.5 on 2024-04-08 19:44

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("content", "0059_minute"),
]

operations = [
migrations.AddField(
model_name="minute",
name="tag",
field=models.CharField(
choices=[("Møtereferat", "Minute"), ("Dokument", "Document")],
default="Møtereferat",
max_length=50,
),
),
]
1 change: 1 addition & 0 deletions app/content/models/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
get_strike_strike_size,
)
from app.content.models.qr_code import QRCode
from app.content.models.minute import Minute
53 changes: 53 additions & 0 deletions app/content/models/minute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
from django.db import models

from app.common.enums import AdminGroup
from app.common.permissions import BasePermissionModel
from app.content.enums import MinuteTagEnum
from app.content.models.user import User
from app.util.models import BaseModel


class Minute(BaseModel, BasePermissionModel):
write_access = (AdminGroup.INDEX,)
read_access = (AdminGroup.INDEX,)

title = models.CharField(max_length=200)
content = models.TextField(default="", blank=True)
tag = models.CharField(
max_length=50, choices=MinuteTagEnum.choices, default=MinuteTagEnum.MINUTE
)
author = models.ForeignKey(
User,
blank=True,
null=True,
default=None,
on_delete=models.SET_NULL,
related_name="meeting_minutes",
)

@classmethod
def has_update_permission(cls, request):
return cls.has_write_permission(request)

@classmethod
def has_destroy_permission(cls, request):
return cls.has_write_permission(request)

@classmethod
def has_retrieve_permission(cls, request):
return cls.has_read_permission(request)

def has_object_read_permission(self, request):
return self.has_read_permission(request)

def has_object_update_permission(self, request):
return self.has_write_permission(request)

def has_object_destroy_permission(self, request):
return self.has_write_permission(request)

def has_object_retrieve_permission(self, request):
return self.has_read_permission(request)

def __str__(self):
return self.title
6 changes: 6 additions & 0 deletions app/content/serializers/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,3 +31,9 @@
DefaultUserSerializer,
UserPermissionsSerializer,
)
from app.content.serializers.minute import (
MinuteCreateSerializer,
MinuteSerializer,
MinuteUpdateSerializer,
MinuteListSerializer,
)
45 changes: 45 additions & 0 deletions app/content/serializers/minute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
from rest_framework import serializers

from app.content.models import Minute, User


class SimpleUserSerializer(serializers.ModelSerializer):
class Meta:
model = User
fields = ("user_id", "first_name", "last_name", "image")


class MinuteCreateSerializer(serializers.ModelSerializer):
class Meta:
model = Minute
fields = ("title", "content", "tag")

def create(self, validated_data):
author = self.context["request"].user
minute = Minute.objects.create(**validated_data, author=author)
return minute


class MinuteSerializer(serializers.ModelSerializer):
author = SimpleUserSerializer(read_only=True)

class Meta:
model = Minute
fields = ("id", "title", "content", "author", "created_at", "updated_at", "tag")


class MinuteUpdateSerializer(serializers.ModelSerializer):
class Meta:
model = Minute
fields = ("id", "title", "content", "tag")

def update(self, instance, validated_data):
return super().update(instance, validated_data)


class MinuteListSerializer(serializers.ModelSerializer):
author = SimpleUserSerializer(read_only=True)

class Meta:
model = Minute
fields = ("id", "title", "author", "created_at", "updated_at", "tag")
2 changes: 2 additions & 0 deletions app/content/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
CheatsheetViewSet,
EventViewSet,
LogEntryViewSet,
MinuteViewSet,
NewsViewSet,
PageViewSet,
QRCodeViewSet,
Expand Down Expand Up @@ -42,6 +43,7 @@
router.register("pages", PageViewSet)
router.register("strikes", StrikeViewSet, basename="strikes")
router.register("log-entries", LogEntryViewSet, basename="log-entries")
router.register("minutes", MinuteViewSet, basename="minutes")

urlpatterns = [
re_path(r"", include(router.urls)),
Expand Down
1 change: 1 addition & 0 deletions app/content/views/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,4 @@
from app.content.views.toddel import ToddelViewSet
from app.content.views.qr_code import QRCodeViewSet
from app.content.views.logentry import LogEntryViewSet
from app.content.views.minute import MinuteViewSet
66 changes: 66 additions & 0 deletions app/content/views/minute.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
from django_filters.rest_framework import DjangoFilterBackend
from rest_framework import filters, status
from rest_framework.response import Response

from app.common.pagination import BasePagination
from app.common.permissions import BasicViewPermission
from app.common.viewsets import BaseViewSet
from app.content.filters import MinuteFilter
from app.content.models import Minute
from app.content.serializers import (
MinuteCreateSerializer,
MinuteListSerializer,
MinuteSerializer,
MinuteUpdateSerializer,
)


class MinuteViewSet(BaseViewSet):
serializer_class = MinuteSerializer
permission_classes = [BasicViewPermission]
pagination_class = BasePagination
queryset = Minute.objects.all()

filter_backends = [DjangoFilterBackend, filters.SearchFilter]
filterset_class = MinuteFilter
search_fields = [
"title",
"author__first_name",
"author__last_name",
"author__user_id",
]

def get_serializer_class(self):
if hasattr(self, "action") and self.action == "list":
return MinuteListSerializer
return super().get_serializer_class()

def create(self, request, *args, **kwargs):
data = request.data
serializer = MinuteCreateSerializer(data=data, context={"request": request})
if serializer.is_valid():
minute = super().perform_create(serializer)
serializer = MinuteSerializer(minute)
return Response(serializer.data, status=status.HTTP_201_CREATED)

return Response(
{"detail": serializer.errors}, status=status.HTTP_400_BAD_REQUEST
)

def update(self, request, *args, **kwargs):
minute = self.get_object()
serializer = MinuteUpdateSerializer(
minute, data=request.data, context={"request": request}
)
if serializer.is_valid():
minute = super().perform_update(serializer)
serializer = MinuteSerializer(minute)
return Response(serializer.data, status=status.HTTP_200_OK)

return Response(
{"detail": serializer.errors}, status=status.HTTP_400_BAD_REQUEST
)

def destroy(self, request, *args, **kwargs):
super().destroy(request, *args, **kwargs)
return Response({"detail": "The minute was deleted"}, status=status.HTTP_200_OK)
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
# Generated by Django 4.2.5 on 2024-03-22 12:36

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
("kontres", "0006_rename_alcohol_agreement_reservation_serves_alcohol"),
]

operations = [
migrations.AddField(
model_name="bookableitem",
name="image",
field=models.URLField(blank=True, max_length=600, null=True),
),
migrations.AddField(
model_name="bookableitem",
name="image_alt",
field=models.CharField(blank=True, max_length=200, null=True),
),
]
27 changes: 27 additions & 0 deletions app/kontres/migrations/0008_reservation_approved_by.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# Generated by Django 4.2.5 on 2024-04-06 09:39

from django.conf import settings
from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
("kontres", "0007_bookableitem_image_bookableitem_image_alt"),
]

operations = [
migrations.AddField(
model_name="reservation",
name="approved_by",
field=models.ForeignKey(
blank=True,
null=True,
on_delete=django.db.models.deletion.SET_NULL,
related_name="approved_reservations",
to=settings.AUTH_USER_MODEL,
),
),
]
Loading

0 comments on commit 3d0726e

Please sign in to comment.