Files
lifenexp/apps/progression/models.py
T

144 lines
4.1 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# apps/progression/models.py
import uuid
from django.conf import settings
from django.db import models
class TaskCompletion(models.Model):
class Status(models.TextChoices):
PENDING = "pending", "En attente"
ACCEPTED = "accepted", "Acceptée"
REJECTED = "rejected", "Refusée"
CANCELLED = "cancelled", "Annulée"
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
player = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="task_completions",
)
task = models.ForeignKey(
"skills.Task",
on_delete=models.PROTECT,
related_name="completions",
)
status = models.CharField(
max_length=16,
choices=Status.choices,
default=Status.ACCEPTED,
)
completed_at = models.DateTimeField()
submitted_at = models.DateTimeField(auto_now_add=True)
note = models.TextField(blank=True)
proof_url = models.URLField(blank=True)
# Évite les doubles créations lors d’un retry de l’API.
idempotency_key = models.CharField(
max_length=100,
null=True,
blank=True,
)
# Snapshot au moment de la validation
task_name_snapshot = models.CharField(max_length=160)
xp_snapshot = models.PositiveIntegerField(default=0)
validated_by = models.ForeignKey(
settings.AUTH_USER_MODEL,
null=True,
blank=True,
on_delete=models.SET_NULL,
related_name="validated_completions",
)
validated_at = models.DateTimeField(null=True, blank=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=("player", "idempotency_key"),
condition=models.Q(idempotency_key__isnull=False),
name="unique_player_idempotency_key",
)
]
indexes = [
models.Index(fields=("player", "-completed_at")),
models.Index(fields=("task", "-completed_at")),
]
class XPTransaction(models.Model):
class Reason(models.TextChoices):
TASK = "task", "Réalisation d’une tâche"
ACHIEVEMENT = "achievement", "Succès"
BONUS = "bonus", "Bonus"
CORRECTION = "correction", "Correction"
REVERSAL = "reversal", "Annulation"
id = models.UUIDField(primary_key=True, default=uuid.uuid4, editable=False)
player = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="xp_transactions",
)
skill = models.ForeignKey(
"skills.Skill",
on_delete=models.PROTECT,
related_name="xp_transactions",
)
# Signé : positif ou négatif
amount = models.IntegerField()
reason = models.CharField(max_length=20, choices=Reason.choices)
completion = models.ForeignKey(
TaskCompletion,
null=True,
blank=True,
on_delete=models.PROTECT,
related_name="xp_transactions",
)
reversed_transaction = models.OneToOneField(
"self",
null=True,
blank=True,
on_delete=models.PROTECT,
related_name="reversal",
)
metadata = models.JSONField(default=dict, blank=True)
created_at = models.DateTimeField(auto_now_add=True)
class Meta:
indexes = [
models.Index(fields=("player", "skill")),
models.Index(fields=("player", "-created_at")),
]
class PlayerSkillProgress(models.Model):
player = models.ForeignKey(
settings.AUTH_USER_MODEL,
on_delete=models.CASCADE,
related_name="skill_progress",
)
skill = models.ForeignKey(
"skills.Skill",
on_delete=models.CASCADE,
related_name="player_progress",
)
xp = models.PositiveBigIntegerField(default=0)
level = models.PositiveIntegerField(default=0)
unlocked_at = models.DateTimeField(null=True, blank=True)
updated_at = models.DateTimeField(auto_now=True)
class Meta:
constraints = [
models.UniqueConstraint(
fields=("player", "skill"),
name="unique_player_skill_progress",
)
]