Skip to content
Open
Show file tree
Hide file tree
Changes from 11 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions backend/apps/github/models/generic_issue_model.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,11 @@ class IssueState(models.TextChoices):
OPEN = "open", "Open"
CLOSED = "closed", "Closed"

class StateReason(models.TextChoices):
"""Issue state reason choices."""

COMPLETED = "completed", "Completed"

title = models.CharField(verbose_name="Title", max_length=1000)
body = models.TextField(verbose_name="Body", default="")

Expand Down
4 changes: 4 additions & 0 deletions backend/apps/owasp/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,7 @@ owasp-update-events:
owasp-update-sponsors:
@echo "Getting OWASP sponsors data"
@CMD="python manage.py owasp_update_sponsors" $(MAKE) exec-backend-command

owasp-crp-recognition-recalculate-scores:
@echo "Recalculating contributor scores"
@CMD="python manage.py owasp_crp_recognition_recalculate_scores" $(MAKE) exec-backend-command
2 changes: 1 addition & 1 deletion backend/apps/owasp/admin/certificate.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.contrib import admin

from apps.owasp.models.certificate import Certificate
from apps.owasp.models.crp.certificate import Certificate


@admin.register(Certificate)
Expand Down
33 changes: 32 additions & 1 deletion backend/apps/owasp/admin/contribution_score.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,13 @@
"""Django admin configuration for ContributionScore model."""

import logging

from django.contrib import admin

from apps.owasp.models.contribution_score import ContributionScore
from apps.owasp.models.crp.contribution_score import ContributionScore
from apps.owasp.score_calculator import ContributionScoreCalculator

logger: logging.Logger = logging.getLogger(__name__)


@admin.register(ContributionScore)
Expand All @@ -14,6 +19,7 @@ class ContributionScoreAdmin(admin.ModelAdmin):
list_filter = ("tier", "nest_created_at")
search_fields = ("github_user__login", "github_user__name")
readonly_fields = ("nest_created_at", "nest_updated_at")
actions = ("recalculate",)

fieldsets = (
(
Expand All @@ -36,3 +42,28 @@ class ContributionScoreAdmin(admin.ModelAdmin):
},
),
)

def recalculate(self, request, queryset):
"""Admin action to recalculate scores for selected users."""
calculator = ContributionScoreCalculator()
updated_count = 0
failed_count = 0

for score in queryset:
try:
calculator.recalculate_user(score.github_user)
updated_count += 1
except Exception:
logger.exception(
"Failed to recalculate score for user %s",
score.github_user.login,
)
failed_count += 1
Comment thread
coderabbitai[bot] marked this conversation as resolved.

self.message_user(
request,
f"Recalculated scores for {updated_count} contributor(s). "
f"Failed for {failed_count} contributor(s).",
)

recalculate.short_description = "Recalculate selected contributors' scores"
2 changes: 1 addition & 1 deletion backend/apps/owasp/admin/leaderboard_snapshot.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.contrib import admin

from apps.owasp.models.leaderboard_snapshot import LeaderboardSnapshot
from apps.owasp.models.crp.leaderboard_snapshot import LeaderboardSnapshot


@admin.register(LeaderboardSnapshot)
Expand Down
2 changes: 1 addition & 1 deletion backend/apps/owasp/admin/scoring_weight.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

from django.contrib import admin

from apps.owasp.models.scoring_weight import ScoringWeight
from apps.owasp.models.crp.scoring_weight import ScoringWeight


@admin.register(ScoringWeight)
Expand Down
4 changes: 4 additions & 0 deletions backend/apps/owasp/exceptions.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,3 +3,7 @@

class SnapshotProcessingError(Exception):
"""Exception raised for errors in snapshot processing."""


class CertificateIssuanceError(Exception):
"""Exception raised for errors in certificate issuance."""
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
"""Command to recalculate contributor scores."""

from django.core.management.base import BaseCommand

from apps.owasp.score_calculator import ContributionScoreCalculator


class Command(BaseCommand):
"""Management command for recalculating contributor scores."""

help = "Recalculate contributor scores and tier assignments."

def handle(self, *args, **options) -> None:
"""Handle the command execution."""
self.stdout.write("Starting score recalculation for all users...")

calculator = ContributionScoreCalculator()
result = calculator.recalculate_all()

self.stdout.write(
self.style.SUCCESS(
f"Score recalculation complete:\n"
f" - Total users: {result['total']}\n"
f" - Created: {result['created']}\n"
f" - Updated: {result['updated']}"
)
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
# Generated by Django 6.0.3 on 2026-06-12 16:25

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("owasp", "0073_scoringweight_certificate_contributionscore_and_more"),
]

operations = [
migrations.AlterModelTable(
name="certificate",
table="owasp_crp_recognition_certificates",
),
migrations.AlterModelTable(
name="contributionscore",
table="owasp_crp_recognition_contribution_scores",
),
migrations.AlterModelTable(
name="leaderboardsnapshot",
table="owasp_crp_recognition_leaderboard_snapshots",
),
migrations.AlterModelTable(
name="scoringweight",
table="owasp_crp_recognition_scoring_weights",
),
]
10 changes: 5 additions & 5 deletions backend/apps/owasp/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,19 +1,19 @@
from .board_of_directors import BoardOfDirectors
from .certificate import Certificate
from .chapter import Chapter
from .committee import Committee
from .contribution_score import ContributionScore
from .crp.certificate import Certificate
from .crp.contribution_score import ContributionScore
from .crp.leaderboard_snapshot import LeaderboardSnapshot
from .crp.recognition_enums import EventTypeChoices, TierChoices
from .crp.scoring_weight import ScoringWeight
from .entity_channel import EntityChannel
from .entity_member import EntityMember
from .event import Event
from .leaderboard_snapshot import LeaderboardSnapshot
from .member_profile import MemberProfile
from .member_snapshot import MemberSnapshot
from .post import Post
from .project import Project
from .project_health_metrics import ProjectHealthMetrics
from .project_health_requirements import ProjectHealthRequirements
from .recognition_enums import EventTypeChoices, TierChoices
from .scoring_weight import ScoringWeight
from .snapshot import Snapshot
from .sponsor import Sponsor
Empty file.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

from apps.common.models import TimestampedModel
from apps.github.models.user import User
from apps.owasp.models.recognition_enums import TierChoices
from apps.owasp.models.crp.recognition_enums import TierChoices


class Certificate(TimestampedModel):
Expand All @@ -22,7 +22,7 @@ class Certificate(TimestampedModel):
class Meta:
"""Model options."""

db_table = "recognition_certificates"
db_table = "owasp_crp_recognition_certificates"
verbose_name_plural = "Certificates"
indexes = [
models.Index(fields=["-issued_at"], name="cert_issued_at_desc"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

from apps.common.models import TimestampedModel
from apps.github.models.user import User
from apps.owasp.models.recognition_enums import TierChoices
from apps.owasp.models.crp.recognition_enums import TierChoices


class ContributionScore(TimestampedModel):
Expand All @@ -18,7 +18,7 @@ class ContributionScore(TimestampedModel):
class Meta:
"""Model options."""

db_table = "recognition_contribution_scores"
db_table = "owasp_crp_recognition_contribution_scores"
verbose_name_plural = "Contribution Scores"
indexes = [
models.Index(fields=["-value"], name="score_total_desc_idx"),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,8 @@
from apps.common.models import TimestampedModel
from apps.github.models.user import User
from apps.owasp.models.chapter import Chapter
from apps.owasp.models.crp.recognition_enums import TierChoices
from apps.owasp.models.project import Project
from apps.owasp.models.recognition_enums import TierChoices


class LeaderboardSnapshot(TimestampedModel):
Expand All @@ -21,7 +21,7 @@ class LeaderboardSnapshot(TimestampedModel):
class Meta:
"""Model options."""

db_table = "recognition_leaderboard_snapshots"
db_table = "owasp_crp_recognition_leaderboard_snapshots"
verbose_name_plural = "Leaderboard Snapshots"
unique_together = ("github_user", "project", "chapter", "snapshot_date")
indexes = [
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
from django.db import models

from apps.common.models import TimestampedModel
from apps.owasp.models.recognition_enums import EventTypeChoices
from apps.owasp.models.crp.recognition_enums import EventTypeChoices


class ScoringWeight(TimestampedModel):
Expand All @@ -18,7 +18,7 @@ class ScoringWeight(TimestampedModel):
class Meta:
"""Model options."""

db_table = "recognition_scoring_weights"
db_table = "owasp_crp_recognition_scoring_weights"
verbose_name_plural = "Scoring Weights"

event_type = models.CharField(
Expand Down
Loading
Loading