Coverage for baibu/metrics/models.py: 100%
19 statements
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
« prev ^ index » next coverage.py v7.10.7, created at 2026-10-06 13:07 +0000
1import uuid
3from django.db import models
4from django.utils.translation import gettext_lazy as _
7class DailyMetric(models.Model):
8 """One aggregate count for one day: never text, names or per-user rows.
10 ``name`` is a metric from ``baibu.metrics.definitions.METRICS``.
11 ``dimension`` is empty for a plain total, or the value a breakdown is
12 split by (a language code, a status, ``scope:tier``, a week number).
13 Retention rows are dated by the first day of the cohort week.
14 """
16 id = models.UUIDField(primary_key=True, default=uuid.uuid7, editable=False)
17 date = models.DateField(db_index=True)
18 name = models.CharField(max_length=64)
19 dimension = models.CharField(max_length=128, blank=True, default="")
20 value = models.BigIntegerField()
21 computed_at = models.DateTimeField(auto_now=True)
23 class Meta:
24 ordering = ["date", "name", "dimension"]
25 constraints = [
26 models.UniqueConstraint(fields=["date", "name", "dimension"], name="metrics_one_value_per_day"),
27 ]
28 indexes = [models.Index(fields=["name", "date"])]
29 verbose_name = _("Daily metric")
30 verbose_name_plural = _("Daily metrics")
32 def __str__(self) -> str:
33 suffix = f" [{self.dimension}]" if self.dimension else ""
34 return f"{self.date} {self.name}{suffix}: {self.value}"