Skip to content

Commit

Permalink
feat: Total activity table (#2168)
Browse files Browse the repository at this point in the history
* feat: Total activity table

* Use update

* Include registration types
  • Loading branch information
faucomte97 committed Sep 7, 2023
1 parent f28e1e4 commit e5153aa
Show file tree
Hide file tree
Showing 8 changed files with 219 additions and 70 deletions.
130 changes: 65 additions & 65 deletions Pipfile.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

25 changes: 25 additions & 0 deletions cfl_common/common/migrations/0042_totalactivity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Generated by Django 3.2.20 on 2023-09-07 01:56

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('common', '0041_populate_gb_counties'),
]

operations = [
migrations.CreateModel(
name='TotalActivity',
fields=[
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
('teacher_registrations', models.PositiveIntegerField(default=0)),
('student_registrations', models.PositiveIntegerField(default=0)),
('independent_registrations', models.PositiveIntegerField(default=0)),
],
options={
'verbose_name_plural': 'Total activity',
},
),
]
30 changes: 30 additions & 0 deletions cfl_common/common/migrations/0043_add_total_activity.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
from django.db import migrations


def add_total_activity(apps, schema_editor):
"""
This creates the only TotalActivity entry that we need to record total activity.
Initialises it with the total number of registrations at the time of the migration.
"""
TotalActivity = apps.get_model("common", "TotalActivity")
Teacher = apps.get_model("common", "Teacher")
Student = apps.get_model("common", "Student")
TotalActivity.objects.create(
teacher_registrations=Teacher.objects.all().count(),
student_registrations=Student.objects.filter(class_field__isnull=False).count(),
independent_registrations=Student.objects.filter(class_field__isnull=True).count(),
)


def remove_total_activity(apps, schema_editor):
TotalActivity = apps.get_model("common", "TotalActivity")
TotalActivity.objects.get(id=1).delete()


class Migration(migrations.Migration):

dependencies = [
("common", "0042_totalactivity"),
]

operations = [migrations.RunPython(add_total_activity, remove_total_activity)]
17 changes: 17 additions & 0 deletions cfl_common/common/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -353,6 +353,23 @@ def __str__(self):
return f"Activity on {self.date}: CSV clicks: {self.csv_click_count}, login cards clicks: {self.login_cards_click_count}, primary pack downloads: {self.primary_coding_club_downloads}, python pack downloads: {self.python_coding_club_downloads}, level control submits: {self.level_control_submits}, teacher lockout resets: {self.teacher_lockout_resets}, indy lockout resets: {self.indy_lockout_resets}, school student lockout resets: {self.school_student_lockout_resets}"


class TotalActivity(models.Model):
"""
A model to record total activity. Meant to only have one entry which records all total activity.
An example of this is total ever registrations.
"""

teacher_registrations = models.PositiveIntegerField(default=0)
student_registrations = models.PositiveIntegerField(default=0)
independent_registrations = models.PositiveIntegerField(default=0)

class Meta:
verbose_name_plural = "Total activity"

def __str__(self):
return "Total activity"


class DynamicElement(models.Model):
"""
This model is meant to allow us to quickly update some elements dynamically on the website without having to
Expand Down
10 changes: 10 additions & 0 deletions portal/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
UserProfile,
DynamicElement,
DailyActivity,
TotalActivity,
)
from django.contrib import admin
from django.contrib.auth.admin import UserAdmin
Expand Down Expand Up @@ -102,6 +103,14 @@ def has_delete_permission(self, request, obj=None):
return False


class TotalActivityAdmin(admin.ModelAdmin, ExportActionMixin):
def has_add_permission(self, request):
return False

def has_delete_permission(self, request, obj=None):
return False


def anonymise_user(user_admin, request, queryset):
for user in queryset:
anonymise(user)
Expand Down Expand Up @@ -144,3 +153,4 @@ def export_as_csv(self, request, queryset):
admin.site.register(SchoolTeacherInvitation, SchoolTeacherInvitationAdmin)
admin.site.register(DynamicElement, DynamicElementAdmin)
admin.site.register(DailyActivity)
admin.site.register(TotalActivity, TotalActivityAdmin)
63 changes: 62 additions & 1 deletion portal/tests/test_views.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
import PyPDF2
import pytest
from aimmo.models import Game
from common.models import Teacher, UserSession, Student, Class, DailyActivity, School, UserProfile
from common.models import Teacher, UserSession, Student, Class, DailyActivity, School, UserProfile, TotalActivity
from common.tests.utils.classes import create_class_directly
from common.tests.utils.organisation import create_organisation_directly, join_teacher_to_organisation
from common.tests.utils.student import (
Expand Down Expand Up @@ -710,6 +710,67 @@ def test_logged_in_as_admin_check(self):

c.logout()

def test_registrations_increment_data(self):
c = Client()

total_activity = TotalActivity.objects.get(id=1)
teacher_registration_count = total_activity.teacher_registrations
student_registration_count = total_activity.student_registrations
independent_registration_count = total_activity.independent_registrations

response = c.post(
reverse("register"),
{
"teacher_signup-teacher_first_name": "Test Name",
"teacher_signup-teacher_last_name": "Test Last Name",
"teacher_signup-teacher_email": "[email protected]",
"teacher_signup-consent_ticked": "on",
"teacher_signup-teacher_password": "$RFVBGT%6yhn",
"teacher_signup-teacher_confirm_password": "$RFVBGT%6yhn",
"g-recaptcha-response": "something",
},
)

assert response.status_code == 302

total_activity = TotalActivity.objects.get(id=1)

assert total_activity.teacher_registrations == teacher_registration_count + 1

response = c.post(
reverse("register"),
{
"independent_student_signup-date_of_birth_day": 7,
"independent_student_signup-date_of_birth_month": 10,
"independent_student_signup-date_of_birth_year": 1997,
"independent_student_signup-name": "Test Name",
"independent_student_signup-email": "[email protected]",
"independent_student_signup-consent_ticked": "on",
"independent_student_signup-password": "$RFVBGT%6yhn",
"independent_student_signup-confirm_password": "$RFVBGT%6yhn",
"g-recaptcha-response": "something",
},
)

assert response.status_code == 302

total_activity = TotalActivity.objects.get(id=1)

assert total_activity.independent_registrations == independent_registration_count + 1

teacher_email, teacher_password = signup_teacher_directly()
create_organisation_directly(teacher_email)
_, _, access_code = create_class_directly(teacher_email)

c.login(username=teacher_email, password=teacher_password)
c.post(reverse("view_class", kwargs={"access_code": access_code}), {"names": "Student 1, Student 2, Student 3"})

assert response.status_code == 302

total_activity = TotalActivity.objects.get(id=1)

assert total_activity.student_registrations == student_registration_count + 3


# CRON view tests

Expand Down
Loading

0 comments on commit e5153aa

Please sign in to comment.