Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Events models #210

Merged
merged 35 commits into from
Oct 5, 2023
Merged
Show file tree
Hide file tree
Changes from 31 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
5eb51dc
events base structura and first DB objects
petrceska Sep 4, 2023
2956a28
meeting points
petrceska Sep 8, 2023
f31f6b0
meeting notes incorporated
petrceska Sep 10, 2023
943f2c9
chore: added django-money
thejoeejoee Sep 14, 2023
3738cee
DB changes
petrceska Sep 15, 2023
6d1c8b2
Merge branch 'chore-django-money' into events
petrceska Sep 16, 2023
cf1743b
DB changes
petrceska Sep 18, 2023
700ab29
DB changes
petrceska Sep 26, 2023
72892d4
Merge branch 'develop' into events
petrceska Sep 26, 2023
541819a
events base structura and first DB objects
petrceska Sep 4, 2023
8b02112
meeting points
petrceska Sep 8, 2023
7d13fc5
meeting notes incorporated
petrceska Sep 10, 2023
45d89fb
DB changes
petrceska Sep 15, 2023
c57f8f9
chore: added django-money
thejoeejoee Sep 14, 2023
9728253
DB changes
petrceska Sep 18, 2023
4c21053
Merge branch 'events' of https://github.com/esnvutbrno/buena-fiesta i…
deawer234 Sep 26, 2023
bada5a0
DB changes
petrceska Sep 26, 2023
1af526e
renaming price to price variant
petrceska Sep 26, 2023
a270fd2
events base structura and first DB objects
petrceska Sep 4, 2023
ac13f80
meeting points
petrceska Sep 8, 2023
a73acbd
meeting notes incorporated
petrceska Sep 10, 2023
e129f1a
DB changes
petrceska Sep 15, 2023
eca65ee
chore: added django-money
thejoeejoee Sep 14, 2023
c3e1a55
DB changes
petrceska Sep 18, 2023
c4cd8c2
DB changes
petrceska Sep 26, 2023
0ce38ac
DB changes
petrceska Sep 26, 2023
b3afbad
renaming price to price variant
petrceska Sep 26, 2023
0d227b4
Merge remote-tracking branch 'origin/events' into events
petrceska Sep 26, 2023
870437c
improved models, more configurations
petrceska Sep 27, 2023
8b0a3ea
configurations admin view
petrceska Sep 27, 2023
38474e9
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 27, 2023
f4ba0b6
db migrations
petrceska Sep 28, 2023
61a37c7
Merge remote-tracking branch 'origin/events_models' into events_models
petrceska Sep 28, 2023
ee954b4
[pre-commit.ci] auto fixes from pre-commit.com hooks
pre-commit-ci[bot] Sep 28, 2023
5992883
pre-commit fixes
petrceska Sep 28, 2023
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 4 additions & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ DC_CMD = $(cmd)
ARG =

MODELS_PNG = models.png
GRAPH_MODELS_CMD = graph_models accounts plugins auth sections \
GRAPH_MODELS_CMD = graph_models accounts plugins auth sections events \
universities esncards buddy_system \
--verbose-names --disable-sort-fields \
--pydot -X 'ContentType|Base*Model' \
Expand All @@ -44,6 +44,9 @@ shell_plus: da
migrate: DA_CMD = migrate ## Runs manage.py migrate for all apps
migrate: da

showmigrations: DA_CMD = showmigrations ## Runs manage.py showmigrations for all apps
showmigrations: da

optimizemigration: DA_CMD = optimizemigration ## Optimize last migration by optimizemigration: app= migration=
optimizemigration: ARG = $(name) $(migration)
optimizemigration: da
Expand Down
3 changes: 3 additions & 0 deletions fiesta/apps/accounts/models/profile.py
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,9 @@ def __str__(self):
f"{self.home_university or (self.home_faculty.university if self.home_faculty else None) or ''} "
)

def is_esn_card_holder(self):
return False


__all__ = [
"UserProfile",
Expand Down
Empty file added fiesta/apps/events/__init__.py
Empty file.
57 changes: 57 additions & 0 deletions fiesta/apps/events/admin.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from __future__ import annotations
from django.contrib import admin

from ..plugins.admin import BaseChildConfigurationAdmin
from .models import Event, EventsConfiguration, Organizer, Participant, Place, PriceVariant
from apps.plugins.models import BasePluginConfiguration


@admin.register(EventsConfiguration)
class EventsConfigurationAdmin(BaseChildConfigurationAdmin):
base_model = BasePluginConfiguration
list_display = (
"name",
"section",
"shared",
"require_confirmation",
"members_can_create",
"online_purchases",
)
show_in_index = True


@admin.register(Event)
class EventAdmin(admin.ModelAdmin):
list_display = ("section", "title", "capacity", "state", "start", "end", "author", "place")
show_in_index = True

# @admin.display(
# description=_("Filled"),
# )
# def filled(self, obj: Section):
# return obj.memberships.count()
# TODO


@admin.register(Organizer)
class OrganizerAdmin(admin.ModelAdmin):
list_display = ("user", "event", "state")
show_in_index = True


@admin.register(Participant)
class ParticipantAdmin(admin.ModelAdmin):
list_display = ("user", "event", "price", "created")
show_in_index = True


@admin.register(Place)
class PlaceAdmin(admin.ModelAdmin):
list_display = ("name", "description", "link", "map_link", "section")
show_in_index = True


@admin.register(PriceVariant)
class PriceVariantAdmin(admin.ModelAdmin):
list_display = ("title", "type", "amount", "event", "available_from", "available_to")
show_in_index = True
17 changes: 17 additions & 0 deletions fiesta/apps/events/apps.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
from __future__ import annotations
from django.utils.translation import gettext_lazy as _

from apps.plugins.plugin import BasePluginAppConfig


class EventsConfig(BasePluginAppConfig):
default_auto_field = "django.db.models.BigAutoField"
name = "apps.events"
verbose_name = _("Events")
emoji = ""
description = _("Fiesta plugin to handle events management and registrations.")

configuration_model = "events.EventsConfiguration"


__all__ = ["EventsConfig"]
Empty file.
16 changes: 16 additions & 0 deletions fiesta/apps/events/models/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
from __future__ import annotations
from .configuration import EventsConfiguration
from .event import Event
from .organizer import Organizer
from .participant import Participant
from .place import Place
from .price_variant import PriceVariant

__all__ = [
"EventsConfiguration",
"Event",
"Organizer",
"Participant",
"Place",
"PriceVariant",
]
29 changes: 29 additions & 0 deletions fiesta/apps/events/models/configuration.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
from __future__ import annotations
from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.plugins.models import BasePluginConfiguration


class EventsConfiguration(BasePluginConfiguration):
require_confirmation = models.BooleanField(
default=True,
verbose_name=_("require confirmation to publish"),
)

members_can_create = models.BooleanField(
default=True,
verbose_name=_("basic members can create an event"),
)

online_purchases = models.BooleanField(
default=True,
verbose_name=_("online purchases"),
)

class Meta:
verbose_name = _("events configuration")
verbose_name_plural = _("events configurations")


__all__ = ["EventsConfiguration"]
138 changes: 138 additions & 0 deletions fiesta/apps/events/models/event.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
from __future__ import annotations

from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.files.storage import NamespacedFilesStorage
from apps.plugins.middleware.plugin import HttpRequest
from apps.utils.models import BaseTimestampedModel

# TODO Maybe pre-registration, registration and paused registration for different field.


class State(models.TextChoices):
DRAFT = "draft", _("Draft")
PUBLISHED = "published", _("Published")
HIDDEN = "hidden", _("Hidden") # Visible only after invite


def has_permission_for_cover_photo_view(request: HttpRequest, name: str) -> bool: # TODO
if request.user.is_authenticated:
return True

return False


class Event(BaseTimestampedModel):
# storage used for cover photos
event_portrait_cover_photo_storage = NamespacedFilesStorage(
"event-portrait-cover-photo",
has_permission=has_permission_for_cover_photo_view,
)

event_landscape_cover_photo_storage = NamespacedFilesStorage(
"event-landscape-cover-photo",
has_permission=has_permission_for_cover_photo_view,
)

title = models.CharField(
max_length=64,
unique=True,
verbose_name=_("title"),
help_text=_("full name of the event"),
)

subtitle = models.TextField(
verbose_name=_("subtitle"),
help_text=_("short description of the event"),
null=True,
blank=True,
)

description = models.TextField(
verbose_name=_("description"),
help_text=_("full description of the event"),
)

capacity = models.SmallIntegerField(
verbose_name=_("capacity"),
help_text=_("capacity of the event"),
)

state = models.CharField(
choices=State.choices,
default=State.DRAFT,
max_length=16,
verbose_name=_("state"),
help_text=_("current state of the event"),
)

start = models.DateTimeField(
verbose_name=_("start"),
help_text=_("when the event starts"),
)

end = models.DateTimeField(
verbose_name=_("end"),
help_text=_("when the event ends"),
null=True,
blank=True,
)

landscape_cover = models.ImageField(
storage=event_landscape_cover_photo_storage,
upload_to=event_landscape_cover_photo_storage.upload_to,
verbose_name=_("landscape cover photo"),
null=True,
blank=True,
)

portrait_cover = models.ImageField(
storage=event_portrait_cover_photo_storage,
upload_to=event_portrait_cover_photo_storage.upload_to,
verbose_name=_("portrait cover photo"),
null=True,
blank=True,
)

place = models.ForeignKey(
"events.Place",
on_delete=models.SET_NULL,
verbose_name=_("place"),
db_index=False,
null=True,
blank=True,
)

author = models.ForeignKey(
to="accounts.User",
on_delete=models.SET_NULL,
related_name="events",
verbose_name=_("author"),
db_index=False,
null=True,
blank=True,
)

section = models.ForeignKey(
to="sections.Section",
on_delete=models.CASCADE,
related_name="events",
verbose_name=_("ESN section"),
help_text=_("Users from this section can join this event."),
db_index=True,
)

def __str__(self):
# return self.title
return f"{self.title} - {self.start}"

class Meta:
ordering = ["start"]
verbose_name = _("event")
verbose_name_plural = _("events")


__all__ = ["Event"]

# TODO hybrid registration, default user, only online (qr), offline registrations (counter, subtract from capacity)
47 changes: 47 additions & 0 deletions fiesta/apps/events/models/organizer.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
from __future__ import annotations

from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.utils.models import BaseTimestampedModel


class Role(models.TextChoices):
EVENT_LEADER = "event_leader", _("Event_leader")
OC = "oc", _("OC")


class Organizer(BaseTimestampedModel):
state = models.CharField(
choices=Role.choices,
default=Role.OC,
verbose_name=_("state"),
help_text=_("current state of the event"),
)

user = models.ForeignKey(
"accounts.User",
on_delete=models.CASCADE,
related_name="event",
verbose_name=_("user"),
db_index=True,
)

event = models.ForeignKey(
"events.Event",
on_delete=models.CASCADE,
related_name="organizer",
verbose_name=_("event"),
db_index=True,
)

class Meta:
verbose_name = _("organizer")
verbose_name_plural = _("organizers")
unique_together = (("user", "event"),)

def __str__(self):
return self.user + self.event


__all__ = ["Organizer"]
60 changes: 60 additions & 0 deletions fiesta/apps/events/models/participant.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
from __future__ import annotations

from django.db import models
from django.utils.translation import gettext_lazy as _

from apps.utils.models import BaseModel


class State(models.TextChoices): # TODO do we need a state if we have an expiration date
WAITING = "waiting", _("Waiting")
CONFIRMED = "confirmed", _("Confirmed")
DELETED = "deleted", _("Deleted")


class Participant(BaseModel):
created = models.DateTimeField(
verbose_name=_("created at"),
help_text=_("when the user placed the ordered (does not have to be paid)"),
)

user = models.ForeignKey(
to="accounts.User",
related_name="user",
on_delete=models.SET_NULL,
null=True,
db_index=True,
verbose_name=_("user"),
)

event = models.ForeignKey(
to="events.Event",
on_delete=models.SET_NULL,
related_name="event",
null=True,
db_index=True,
verbose_name=_("event"),
)

price = models.ForeignKey(
to="events.PriceVariant",
on_delete=models.SET_NULL,
verbose_name=_("price"),
related_name="price",
null=True,
db_index=False,
)

def __str__(self):
return self.title

class Meta:
unique_together = (("event", "user"),)
verbose_name = _("participant")
verbose_name_plural = _("participants")
ordering = ["created"]


__all__ = ["Participant"]

# TODO problematika ověřování lidí (QR check-in)
Loading