Compare commits
3 Commits
6ca6f1390c
...
da0767a0e9
Author | SHA1 | Date | |
---|---|---|---|
da0767a0e9 | |||
188824d53b | |||
35d8fec2a3 |
@ -1,4 +1,5 @@
|
|||||||
import sys
|
import sys
|
||||||
|
import traceback
|
||||||
|
|
||||||
from django.views.debug import ExceptionReporter
|
from django.views.debug import ExceptionReporter
|
||||||
from django.core import mail
|
from django.core import mail
|
||||||
@ -9,6 +10,7 @@ class AdminEmailReporter:
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def report(self):
|
def report(self):
|
||||||
|
try:
|
||||||
reporter = ExceptionReporter(None, *sys.exc_info())
|
reporter = ExceptionReporter(None, *sys.exc_info())
|
||||||
message = f"Failed to run task\n{reporter.get_traceback_text()}"
|
message = f"Failed to run task\n{reporter.get_traceback_text()}"
|
||||||
html_message = reporter.get_traceback_html()
|
html_message = reporter.get_traceback_html()
|
||||||
@ -18,3 +20,5 @@ class AdminEmailReporter:
|
|||||||
# fail_silently=True,
|
# fail_silently=True,
|
||||||
html_message=html_message,
|
html_message=html_message,
|
||||||
)
|
)
|
||||||
|
except Exception:
|
||||||
|
print(traceback.format_exc())
|
||||||
|
24
membershipworks/migrations/0007_eventmeetingtime_duration.py
Normal file
24
membershipworks/migrations/0007_eventmeetingtime_duration.py
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
# Generated by Django 5.0.1 on 2024-01-03 19:22
|
||||||
|
|
||||||
|
import django.db.models.expressions
|
||||||
|
from django.db import migrations, models
|
||||||
|
|
||||||
|
|
||||||
|
class Migration(migrations.Migration):
|
||||||
|
dependencies = [
|
||||||
|
("membershipworks", "0006_eventext_instructor_flat_rate_and_more"),
|
||||||
|
]
|
||||||
|
|
||||||
|
operations = [
|
||||||
|
migrations.AddField(
|
||||||
|
model_name="eventmeetingtime",
|
||||||
|
name="duration",
|
||||||
|
field=models.GeneratedField(
|
||||||
|
db_persist=False,
|
||||||
|
expression=django.db.models.expressions.CombinedExpression(
|
||||||
|
models.F("end"), "-", models.F("start")
|
||||||
|
),
|
||||||
|
output_field=models.DurationField(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]
|
@ -415,13 +415,7 @@ class EventInstructor(models.Model):
|
|||||||
|
|
||||||
class EventExtManager(models.Manager["EventExt"]):
|
class EventExtManager(models.Manager["EventExt"]):
|
||||||
def get_queryset(self) -> models.QuerySet["EventExt"]:
|
def get_queryset(self) -> models.QuerySet["EventExt"]:
|
||||||
return (
|
return super().get_queryset().annotate(duration=Sum("meeting_times__duration"))
|
||||||
super()
|
|
||||||
.get_queryset()
|
|
||||||
.annotate(duration=Sum(F("meeting_times__end") - F("meeting_times__start")))
|
|
||||||
)
|
|
||||||
# TODO: use simpler expression when GeneratedField fixed
|
|
||||||
# return super().get_queryset().annotate(duration=Sum("meeting_times__duration"))
|
|
||||||
|
|
||||||
|
|
||||||
class EventExt(Event):
|
class EventExt(Event):
|
||||||
@ -446,29 +440,18 @@ class EventExt(Event):
|
|||||||
verbose_name = "event"
|
verbose_name = "event"
|
||||||
|
|
||||||
|
|
||||||
class EventMeetingTimeManager(models.Manager["EventMeetingTime"]):
|
|
||||||
def get_queryset(self) -> models.QuerySet["EventMeetingTime"]:
|
|
||||||
return super().get_queryset().annotate(duration=F("end") - F("start"))
|
|
||||||
|
|
||||||
|
|
||||||
class EventMeetingTime(models.Model):
|
class EventMeetingTime(models.Model):
|
||||||
objects = EventMeetingTimeManager()
|
|
||||||
|
|
||||||
event = models.ForeignKey(
|
event = models.ForeignKey(
|
||||||
EventExt, on_delete=models.CASCADE, related_name="meeting_times"
|
EventExt, on_delete=models.CASCADE, related_name="meeting_times"
|
||||||
)
|
)
|
||||||
start = models.DateTimeField()
|
start = models.DateTimeField()
|
||||||
end = models.DateTimeField()
|
end = models.DateTimeField()
|
||||||
|
|
||||||
# TODO: Should use generated field instead of manager, but this is
|
duration = models.GeneratedField(
|
||||||
# broken due to current Django bug, pending next release (> 5.0)
|
expression=F("end") - F("start"),
|
||||||
# ref: https://code.djangoproject.com/ticket/35019
|
output_field=models.DurationField(),
|
||||||
|
db_persist=False,
|
||||||
# duration = models.GeneratedField(
|
)
|
||||||
# expression=F("end") - F("start"),
|
|
||||||
# output_field=models.DurationField(),
|
|
||||||
# db_persist=False,
|
|
||||||
# )
|
|
||||||
|
|
||||||
class Meta:
|
class Meta:
|
||||||
constraints = [
|
constraints = [
|
||||||
|
@ -22,7 +22,7 @@ GROUPS_REGEX = "|".join(
|
|||||||
# A group name must start and end with a letter, number or underscore.
|
# A group name must start and end with a letter, number or underscore.
|
||||||
# In between additionally spaces, dashes and dots are allowed.
|
# In between additionally spaces, dashes and dots are allowed.
|
||||||
def sanitize_group_name(name):
|
def sanitize_group_name(name):
|
||||||
sanitized_body = re.sub(r"[^0-9A-Za-z_ -.]", ".", name)
|
sanitized_body = re.sub(r"[^0-9A-Za-z_ -.]+", ".", name)
|
||||||
sanitized_start_end = re.sub("^[^0-9A-Za-z_]|[^0-9A-Za-z_]$", "_", sanitized_body)
|
sanitized_start_end = re.sub("^[^0-9A-Za-z_]|[^0-9A-Za-z_]$", "_", sanitized_body)
|
||||||
|
|
||||||
return "MW_" + sanitized_start_end
|
return "MW_" + sanitized_start_end
|
||||||
@ -30,7 +30,7 @@ def sanitize_group_name(name):
|
|||||||
|
|
||||||
# From an API error message: "Username must only contain numbers, letters and dots!"
|
# From an API error message: "Username must only contain numbers, letters and dots!"
|
||||||
def sanitize_user_name(name):
|
def sanitize_user_name(name):
|
||||||
return re.sub(r"[^0-9a-z.]", ".", name.lower()).strip(".")
|
return re.sub(r"[^0-9a-z.]+", ".", name.lower()).strip(".")
|
||||||
|
|
||||||
|
|
||||||
async def make_groups(udm):
|
async def make_groups(udm):
|
||||||
|
Loading…
Reference in New Issue
Block a user