Skip to content

Commit 79a078f

Browse files
committed
added expanded courses panel for easy double counting, fixed double counting when transcript parsing and adding courses, miscellaneous fixes (edit mode, renaming, copying)
1 parent cb1bca5 commit 79a078f

24 files changed

Lines changed: 1554 additions & 538 deletions
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
# Generated by Django 5.0.2 on 2025-03-12 02:24
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("degree", "0001_initial"),
10+
]
11+
12+
operations = [
13+
migrations.AddField(
14+
model_name="fulfillment",
15+
name="selected_rules",
16+
field=models.ManyToManyField(
17+
blank=True,
18+
help_text="\nThe rules this course fulfills that should be shown in the open-ended rule box \n(as opposed to the expandable box). Blank if this course should not be included in\nany open-ended rule boxes.\n",
19+
related_name="+",
20+
to="degree.rule",
21+
),
22+
),
23+
]
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Generated by Django 5.0.2 on 2025-03-12 06:56
2+
3+
from django.db import migrations, models
4+
5+
6+
class Migration(migrations.Migration):
7+
8+
dependencies = [
9+
("degree", "0002_fulfillment_selected_rules"),
10+
]
11+
12+
operations = [
13+
migrations.RemoveField(
14+
model_name="fulfillment",
15+
name="selected_rules",
16+
),
17+
migrations.AddField(
18+
model_name="fulfillment",
19+
name="unselected_rules",
20+
field=models.ManyToManyField(
21+
blank=True,
22+
help_text="\nThe rules this course fulfills that should be shown in the open-ended rule box \n(as opposed to the expandable box). Blank if this course should not be included in\nany open-ended rule boxes.\n",
23+
related_name="selected",
24+
to="degree.rule",
25+
),
26+
),
27+
]

backend/degree/models.py

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -397,10 +397,21 @@ def copy(self, new_name: str) -> DegreePlan:
397397
new_degree_plan.degrees.add(degree)
398398

399399
# this also handles updating satisfaction statuses
400+
401+
400402
for fulfillment in self.fulfillments.all():
403+
for field in fulfillment._meta.fields:
404+
print(getattr(fulfillment, field.name))
405+
406+
rules = fulfillment.rules.all()
407+
unselected_rules = fulfillment.unselected_rules.all()
408+
401409
fulfillment.pk = None
402410
fulfillment.degree_plan = new_degree_plan
403411
fulfillment.save()
412+
fulfillment.rules.set(rules)
413+
fulfillment.unselected_rules.set(unselected_rules)
414+
404415

405416
return new_degree_plan
406417

@@ -443,6 +454,18 @@ class Fulfillment(models.Model):
443454
"""
444455
),
445456
)
457+
unselected_rules = models.ManyToManyField(
458+
Rule,
459+
related_name="selected",
460+
blank=True,
461+
help_text=dedent(
462+
"""
463+
The rules this course fulfills that should be shown in the open-ended rule box
464+
(as opposed to the expandable box). Blank if this course should not be included in
465+
any open-ended rule boxes.
466+
"""
467+
),
468+
)
446469

447470
class Meta:
448471
unique_together = ("degree_plan", "full_code")

backend/degree/serializers.py

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -121,20 +121,27 @@ def to_internal_value(self, data):
121121

122122
class Meta:
123123
model = Fulfillment
124-
fields = ["id", "degree_plan", "full_code", "course", "semester", "rules"]
124+
fields = ["id", "degree_plan", "full_code", "course", "semester", "rules", "unselected_rules"]
125125

126126
def validate(self, data):
127127
data = super().validate(data)
128128
rules = data.get("rules") # for patch requests without a rules field
129+
unselected_rules = data.get("unselected_rules")
129130
full_code = data.get("full_code")
130131
degree_plan = data.get("degree_plan")
131132

132-
if rules is None and full_code is None and degree_plan is None:
133+
if rules is None and unselected_rules is None and full_code is None and degree_plan is None:
133134
return data # Nothing to validate
134135
if rules is None and self.instance is not None:
135136
rules = self.instance.rules.all()
136137
elif rules is None:
137138
rules = []
139+
140+
if unselected_rules is None and self.instance is not None:
141+
unselected_rules = self.instance.unselected_rules.all()
142+
elif unselected_rules is None:
143+
unselected_rules = []
144+
138145
if full_code is None:
139146
full_code = self.instance.full_code
140147
if degree_plan is None:

0 commit comments

Comments
 (0)