feat(submissions): scoped submissions per user/matchs, sync from polylan

This commit is contained in:
2026-09-16 13:12:22 +02:00
parent 85e67599af
commit fabf06e6d4
35 changed files with 1008 additions and 92 deletions
@@ -0,0 +1,84 @@
import uuid
import django.db.models.deletion
from django.conf import settings
from django.db import migrations, models
class Migration(migrations.Migration):
dependencies = [
("submissions", "0005_submission_event_required"),
("games", "0007_eventgame_apibot_token"),
migrations.swappable_dependency(settings.AUTH_USER_MODEL),
]
operations = [
migrations.CreateModel(
name="Scope",
fields=[
(
"id",
models.UUIDField(
default=uuid.uuid4,
editable=False,
primary_key=True,
serialize=False,
),
),
("created_at", models.DateTimeField(auto_now_add=True)),
("updated_at", models.DateTimeField(auto_now=True)),
(
"external_id",
models.PositiveIntegerField(
blank=True,
help_text="Legacy AAndT match id, set when synced automatically.",
null=True,
),
),
("name", models.CharField(max_length=255)),
(
"is_active",
models.BooleanField(
default=True,
help_text="Whether submissions are currently accepted for this scope.",
),
),
(
"synced_at",
models.DateTimeField(
blank=True,
help_text="Last time this scope was synced from the AAndT API.",
null=True,
),
),
(
"assigned_users",
models.ManyToManyField(
blank=True,
help_text="Users allowed to submit scores for this scope.",
related_name="scopes",
to=settings.AUTH_USER_MODEL,
),
),
(
"event_game",
models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="scopes",
to="games.eventgame",
),
),
],
options={
"ordering": ["-created_at"],
},
),
migrations.AddConstraint(
model_name="scope",
constraint=models.UniqueConstraint(
condition=models.Q(("external_id__isnull", False)),
fields=("event_game", "external_id"),
name="unique_scope_external_id_per_event_game",
),
),
]
@@ -0,0 +1,37 @@
import uuid
import django.db.models.deletion
from django.db import migrations, models
def delete_existing_submissions(apps, schema_editor):
"""Submissions predate Scope and can't be backfilled with one; wipe them."""
Submission = apps.get_model("submissions", "Submission")
Submission.objects.all().delete()
class Migration(migrations.Migration):
# Deleting existing submissions (which cascades to their files/crops) fires
# deferred FK triggers on postgres; altering the same table right after in
# the same transaction hits "pending trigger events", so run non-atomically.
atomic = False
dependencies = [
("submissions", "0006_scope"),
]
operations = [
migrations.RunPython(delete_existing_submissions, migrations.RunPython.noop),
migrations.AddField(
model_name="submission",
name="scope",
field=models.ForeignKey(
default=uuid.uuid4,
help_text="The match this submission's score is for.",
on_delete=django.db.models.deletion.CASCADE,
related_name="submissions",
to="submissions.scope",
),
preserve_default=False,
),
]
@@ -0,0 +1,17 @@
# Generated by Django 6.0.5 on 2026-09-16 09:27
from django.db import migrations
class Migration(migrations.Migration):
dependencies = [
("submissions", "0007_submission_scope"),
]
operations = [
migrations.RemoveField(
model_name="submission",
name="game",
),
]