From 6c7c2ff5dfda25bf59d0b1b06e02f8d4f0833b05 Mon Sep 17 00:00:00 2001 From: Altafur Rahman Date: Mon, 6 Jan 2025 21:54:11 +0600 Subject: [PATCH] feat: add ContributorStats model for tracking contributor activity (#3208) --- website/migrations/0179_contributorstats.py | 60 +++++++++++++++++++++ website/models.py | 40 ++++++++++---- 2 files changed, 89 insertions(+), 11 deletions(-) create mode 100644 website/migrations/0179_contributorstats.py diff --git a/website/migrations/0179_contributorstats.py b/website/migrations/0179_contributorstats.py new file mode 100644 index 000000000..08fea502b --- /dev/null +++ b/website/migrations/0179_contributorstats.py @@ -0,0 +1,60 @@ +# Generated by Django 5.1.3 on 2025-01-06 13:17 + +import django.db.models.deletion +from django.db import migrations, models + + +class Migration(migrations.Migration): + dependencies = [ + ("website", "0178_alter_ip_agent"), + ] + + operations = [ + migrations.CreateModel( + name="ContributorStats", + fields=[ + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField()), + ("commits", models.PositiveIntegerField(default=0)), + ("issues_opened", models.PositiveIntegerField(default=0)), + ("issues_closed", models.PositiveIntegerField(default=0)), + ("pull_requests", models.PositiveIntegerField(default=0)), + ("comments", models.PositiveIntegerField(default=0)), + ( + "granularity", + models.CharField( + choices=[("day", "Day"), ("month", "Month")], + default="day", + max_length=10, + ), + ), + ( + "contributor", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="stats", + to="website.contributor", + ), + ), + ( + "repo", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="stats", + to="website.repo", + ), + ), + ], + options={ + "unique_together": {("contributor", "repo", "date", "granularity")}, + }, + ), + ] diff --git a/website/models.py b/website/models.py index a9029ae03..4e4735a7b 100644 --- a/website/models.py +++ b/website/models.py @@ -935,17 +935,6 @@ def __str__(self): return self.name -# class ContributorStats(models.Model): -# username = models.CharField(max_length=255, unique=True) -# commits = models.IntegerField(default=0) -# issues_opened = models.IntegerField(default=0) -# issues_closed = models.IntegerField(default=0) -# prs = models.IntegerField(default=0) -# comments = models.IntegerField(default=0) -# assigned_issues = models.IntegerField(default=0) -# created = models.DateTimeField(auto_now_add=True) - - class Contribution(models.Model): CONTRIBUTION_TYPES = [ ("commit", "Commit"), @@ -1316,3 +1305,32 @@ def save(self, *args, **kwargs): def __str__(self): return f"{self.project.name}/{self.name}" + + +class ContributorStats(models.Model): + contributor = models.ForeignKey(Contributor, on_delete=models.CASCADE, related_name="stats") + repo = models.ForeignKey(Repo, on_delete=models.CASCADE, related_name="stats") + + # This will represent either a specific day or the first day of a month. + date = models.DateField() + + # Store counts + commits = models.PositiveIntegerField(default=0) + issues_opened = models.PositiveIntegerField(default=0) + issues_closed = models.PositiveIntegerField(default=0) + pull_requests = models.PositiveIntegerField(default=0) + comments = models.PositiveIntegerField(default=0) + + # "day" for daily entries, "month" for monthly entries + granularity = models.CharField( + max_length=10, choices=[("day", "Day"), ("month", "Month")], default="day" + ) + + class Meta: + # You can't have two different stats for the same date+granularity + unique_together = ("contributor", "repo", "date", "granularity") + + def __str__(self): + return ( + f"{self.contributor.name} in {self.repo.name} " f"on {self.date} [{self.granularity}]" + )