Skip to content

Commit

Permalink
Merge pull request #60 from pennlabs/degree-names
Browse files Browse the repository at this point in the history
Add degree and concentration names
  • Loading branch information
Clue88 authored Mar 28, 2024
2 parents dd8e591 + a8241c3 commit 640d5d3
Show file tree
Hide file tree
Showing 31 changed files with 619 additions and 186 deletions.
8 changes: 4 additions & 4 deletions backend/PennCourses/settings/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -201,10 +201,10 @@
"rest_framework.authentication.BasicAuthentication",
"accounts.authentication.PlatformAuthentication",
],
'DEFAULT_PARSER_CLASSES': (
'rest_framework.parsers.JSONParser',
'rest_framework.parsers.FormParser',
'rest_framework.parsers.MultiPartParser',
"DEFAULT_PARSER_CLASSES": (
"rest_framework.parsers.JSONParser",
"rest_framework.parsers.FormParser",
"rest_framework.parsers.MultiPartParser",
),
}

Expand Down
9 changes: 5 additions & 4 deletions backend/courses/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -313,16 +313,17 @@ def filter_choices(queryset, choices):

return filter_choices


def degree_rules_filter(queryset, rule_ids):
"""
:param queryset: initial Course object queryset
:param rule_ids: Comma separated string of of Rule ids to filter by. If the rule does not
have a q object, it does not filter the queryset.
have a q object, it does not filter the queryset.
"""
if not rule_ids:
return queryset
query = Q()
for rule_id in rule_ids.split(","):
for rule_id in rule_ids.split(","):
try:
rule = Rule.objects.get(id=int(rule_id))
except Rule.DoesNotExist | ValueError:
Expand Down Expand Up @@ -366,7 +367,7 @@ def filter_queryset(self, request, queryset, view):
if len(meeting_query) > 0:
queryset = meeting_filter(queryset, meeting_query)

return queryset.distinct("full_code") # TODO: THIS IS A BREAKING CHANGE FOR PCX
return queryset.distinct("full_code") # TODO: THIS IS A BREAKING CHANGE FOR PCX

def get_schema_operation_parameters(self, view):
return [
Expand All @@ -379,7 +380,7 @@ def get_schema_operation_parameters(self, view):
"a string of comma-separated Rule ids. If multiple Rule ids "
"are passed then filtered courses satisfy all the rules."
),
"schema": {"type": "string"}
"schema": {"type": "string"},
},
{
"name": "type",
Expand Down
10 changes: 7 additions & 3 deletions backend/courses/management/commands/recompute_soft_state.py
Original file line number Diff line number Diff line change
Expand Up @@ -98,8 +98,10 @@ def recompute_enrollment():
"""
)


# course credits = sum(section credis for all activities)
COURSE_CREDITS_RAW_SQL = dedent("""
COURSE_CREDITS_RAW_SQL = dedent(
"""
WITH CourseCredits AS (
SELECT U0."id", SUM(U2."activity_cus") AS total_credits
FROM "courses_course" U0
Expand All @@ -119,13 +121,15 @@ def recompute_enrollment():
"""
)


def recompute_course_credits(
model=Course # so this function can be used in migrations (see django.db.migrations.RunPython)
):
model=Course, # so this function can be used in migrations (see django.db.migrations.RunPython)
):

with connection.cursor() as cursor:
cursor.execute(COURSE_CREDITS_RAW_SQL)


def recompute_precomputed_fields(verbose=False):
"""
Recomputes the following precomputed fields:
Expand Down
7 changes: 3 additions & 4 deletions backend/courses/migrations/0064_merge_20240209_2348.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,8 @@
class Migration(migrations.Migration):

dependencies = [
('courses', '0061_merge_20231112_1524'),
('courses', '0063_auto_20231212_1750'),
("courses", "0061_merge_20231112_1524"),
("courses", "0063_auto_20231212_1750"),
]

operations = [
]
operations = []
41 changes: 34 additions & 7 deletions backend/courses/migrations/0065_auto_20240211_1321.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,18 +6,45 @@
class Migration(migrations.Migration):

dependencies = [
('courses', '0064_merge_20240209_2348'),
("courses", "0064_merge_20240209_2348"),
]

operations = [
migrations.AlterField(
model_name='course',
name='num_activities',
field=models.IntegerField(default=0, help_text='\nThe number of distinct activities belonging to this course (precomputed for efficiency).\nMaintained by the registrar import / recomputestats script.\n'),
model_name="course",
name="num_activities",
field=models.IntegerField(
default=0,
help_text="\nThe number of distinct activities belonging to this course (precomputed for efficiency).\nMaintained by the registrar import / recomputestats script.\n",
),
),
migrations.AlterField(
model_name='section',
name='activity',
field=models.CharField(choices=[('', 'Undefined'), ('CLN', 'Clinic'), ('CRT', 'Clinical Rotation'), ('DAB', 'Dissertation Abroad'), ('DIS', 'Dissertation'), ('DPC', 'Doctoral Program Exchange'), ('FLD', 'Field Work'), ('HYB', 'Hybrid'), ('IND', 'Independent Study'), ('LAB', 'Lab'), ('LEC', 'Lecture'), ('MST', 'Masters Thesis'), ('ONL', 'Online'), ('PRC', 'Practicum'), ('REC', 'Recitation'), ('SEM', 'Seminar'), ('SRT', 'Senior Thesis'), ('STU', 'Studio')], db_index=True, help_text='The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings: <table width=100%><tr><td>""</td><td>"Undefined"</td></tr><tr><td>"CLN"</td><td>"Clinic"</td></tr><tr><td>"CRT"</td><td>"Clinical Rotation"</td></tr><tr><td>"DAB"</td><td>"Dissertation Abroad"</td></tr><tr><td>"DIS"</td><td>"Dissertation"</td></tr><tr><td>"DPC"</td><td>"Doctoral Program Exchange"</td></tr><tr><td>"FLD"</td><td>"Field Work"</td></tr><tr><td>"HYB"</td><td>"Hybrid"</td></tr><tr><td>"IND"</td><td>"Independent Study"</td></tr><tr><td>"LAB"</td><td>"Lab"</td></tr><tr><td>"LEC"</td><td>"Lecture"</td></tr><tr><td>"MST"</td><td>"Masters Thesis"</td></tr><tr><td>"ONL"</td><td>"Online"</td></tr><tr><td>"PRC"</td><td>"Practicum"</td></tr><tr><td>"REC"</td><td>"Recitation"</td></tr><tr><td>"SEM"</td><td>"Seminar"</td></tr><tr><td>"SRT"</td><td>"Senior Thesis"</td></tr><tr><td>"STU"</td><td>"Studio"</td></tr></table>', max_length=50),
model_name="section",
name="activity",
field=models.CharField(
choices=[
("", "Undefined"),
("CLN", "Clinic"),
("CRT", "Clinical Rotation"),
("DAB", "Dissertation Abroad"),
("DIS", "Dissertation"),
("DPC", "Doctoral Program Exchange"),
("FLD", "Field Work"),
("HYB", "Hybrid"),
("IND", "Independent Study"),
("LAB", "Lab"),
("LEC", "Lecture"),
("MST", "Masters Thesis"),
("ONL", "Online"),
("PRC", "Practicum"),
("REC", "Recitation"),
("SEM", "Seminar"),
("SRT", "Senior Thesis"),
("STU", "Studio"),
],
db_index=True,
help_text='The section activity, e.g. `LEC` for CIS-120-001 (2020A). Options and meanings: <table width=100%><tr><td>""</td><td>"Undefined"</td></tr><tr><td>"CLN"</td><td>"Clinic"</td></tr><tr><td>"CRT"</td><td>"Clinical Rotation"</td></tr><tr><td>"DAB"</td><td>"Dissertation Abroad"</td></tr><tr><td>"DIS"</td><td>"Dissertation"</td></tr><tr><td>"DPC"</td><td>"Doctoral Program Exchange"</td></tr><tr><td>"FLD"</td><td>"Field Work"</td></tr><tr><td>"HYB"</td><td>"Hybrid"</td></tr><tr><td>"IND"</td><td>"Independent Study"</td></tr><tr><td>"LAB"</td><td>"Lab"</td></tr><tr><td>"LEC"</td><td>"Lecture"</td></tr><tr><td>"MST"</td><td>"Masters Thesis"</td></tr><tr><td>"ONL"</td><td>"Online"</td></tr><tr><td>"PRC"</td><td>"Practicum"</td></tr><tr><td>"REC"</td><td>"Recitation"</td></tr><tr><td>"SEM"</td><td>"Seminar"</td></tr><tr><td>"SRT"</td><td>"Senior Thesis"</td></tr><tr><td>"STU"</td><td>"Studio"</td></tr></table>',
max_length=50,
),
),
]
19 changes: 13 additions & 6 deletions backend/courses/migrations/0066_course_credits.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,23 @@
class Migration(migrations.Migration):

dependencies = [
('courses', '0065_auto_20240211_1321'),
("courses", "0065_auto_20240211_1321"),
]

operations = [
migrations.AddField(
model_name='course',
name='credits',
field=models.DecimalField(blank=True, db_index=True, decimal_places=2, help_text='The number of credits this course takes. This is precomputed for efficiency.', max_digits=4, null=True),
model_name="course",
name="credits",
field=models.DecimalField(
blank=True,
db_index=True,
decimal_places=2,
help_text="The number of credits this course takes. This is precomputed for efficiency.",
max_digits=4,
null=True,
),
),
migrations.RunSQL(
COURSE_CREDITS_RAW_SQL,
)
]
),
]
2 changes: 1 addition & 1 deletion backend/courses/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ class Course(models.Model):
db_index=True,
help_text="The number of credits this course takes. This is precomputed for efficiency.",
)

prerequisites = models.TextField(
blank=True,
help_text="Text describing the prereqs for a course, e.g. 'CIS 120, 160' for CIS-121.",
Expand Down
1 change: 1 addition & 0 deletions backend/courses/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,7 @@ class Meta:
]
read_only_fields = fields


class CourseDetailSerializer(CourseListSerializer):
crosslistings = serializers.SlugRelatedField(
slug_field="full_code",
Expand Down
11 changes: 10 additions & 1 deletion backend/degree/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,14 @@
from django.urls import reverse
from django.utils.html import format_html

from degree.models import Degree, DegreePlan, DoubleCountRestriction, Rule, SatisfactionStatus, Fulfillment
from degree.models import (
Degree,
DegreePlan,
DoubleCountRestriction,
Rule,
SatisfactionStatus,
Fulfillment,
)


# Register your models here.
Expand All @@ -18,10 +25,12 @@ class RuleAdmin(admin.ModelAdmin):
admin.site.register(DegreePlan)
admin.site.register(SatisfactionStatus)


@admin.register(Fulfillment)
class FulfillmentAdmin(admin.ModelAdmin):
autocomplete_fields = ["rules"]


@admin.register(DoubleCountRestriction)
class DoubleCountRestrictionAdmin(admin.ModelAdmin):
autocomplete_fields = ["rule", "other_rule"]
Expand Down
8 changes: 4 additions & 4 deletions backend/degree/management/commands/load_degrees.py
Original file line number Diff line number Diff line change
Expand Up @@ -45,12 +45,12 @@ def handle(self, *args, **kwargs):

created_count = 0
for degree_file in listdir(directory):
degree_match = re.match(
r"(\d+)-(\w+)-(\w+)-(\w+)(?:-(\w+))?", degree_file
)
degree_match = re.match(r"(\d+)-(\w+)-(\w+)-(\w+)(?:-(\w+))?", degree_file)
if not degree_match:
if kwargs["verbosity"]:
print("Skipping {degree_file} because its name does not follow the format of a degree file.")
print(
"Skipping {degree_file} because its name does not follow the format of a degree file."
)
continue
year, program, degree, major, concentration = degree_match.groups()
if program not in program_code_to_name:
Expand Down
Loading

0 comments on commit 640d5d3

Please sign in to comment.