Skip to content
Open
Show file tree
Hide file tree
Changes from all 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
18,690 changes: 18,605 additions & 85 deletions fixtures/test_package.json

Large diffs are not rendered by default.

14 changes: 14 additions & 0 deletions src/intrepid/test_settings.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import os

from intrepid.settings import * # noqa: F401, F403

MIGRATION_MODULES = {
'fluid_permissions': 'test_migrations.fluid_permissions',
}

FIXTURE_DIRS = [
os.path.join(BASE_DIR, '..', 'fixtures'),
]

# Disable HTTP Basic Auth for test client requests
BASICAUTH_DISABLE = True
174 changes: 174 additions & 0 deletions src/package/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -214,6 +214,180 @@ def save(self) -> None:
self.user_session[key] = value


class FastFTEForm(forms.Form):
"""
Optimized version of FTEForm.
Accepts prefetched site_texts dict and batch-fetches
AccountBandingChoices instead of per-type queries.
"""

currency = forms.ModelChoiceField(
queryset=models.Country.objects.exclude(
name__in=["EUROZONE", "Eurozone", "eurozone"]
),
help_text="",
label="",
)
fte = forms.IntegerField(
help_text="",
label="",
)

def __init__(self, *args, **kwargs):
self.user_session = kwargs.pop("user_session")
self.user = kwargs.pop("user")
self.banding_types = kwargs.pop("banding_types")
self.site_texts = kwargs.pop("site_texts", None)

super(FastFTEForm, self).__init__(*args, **kwargs)

def get_site_text(key):
if self.site_texts and key in self.site_texts:
return self.site_texts[key].body
return SiteText.objects.get(key=key).body

self.fields["currency"].help_text = get_site_text(
"select_currency_note"
)
self.fields["fte"].help_text = get_site_text(
"fte_student_count_prompt"
)
self.fields["fte"].label = get_site_text("institutions_fte")

if self.user:
self.fields["fte"].initial = self.user.profile.fte
else:
self.fields["fte"].initial = self.user_session.get("fte", 0)

self.helper = FormHelper()

your_currency = get_site_text("your_currency")

self.helper.layout = Layout(
HTML(
'<h4 id="currency_section">' + your_currency + "</h4>"
),
HTML(
"<p><small>{}</small></p>".format(
get_site_text("after_currency_bandings_info")
)
),
"currency",
)

if self.user:
self.fields["currency"].initial = (
self.user.profile.default_currency
if self.user.profile.default_currency
else None
)
else:
self.fields["currency"].initial = self.user_session.get(
"currency", 0
)

if not self.fields["currency"].initial:
self.fields.pop("fte")
else:
self.helper.layout.append(
Layout(
HTML(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Somewhat curious offloading the HTML generation into this routine, rather than using a template?

"<h4>{}</h4>".format(
get_site_text("institution_details")
)
),
"fte",
)
)

if self.fields["currency"].initial:
# Batch-fetch all AccountBandingChoices at once
if self.user:
account_choices = {
abc.banding_type_id: abc
for abc in accm.AccountBandingChoices.objects.filter(
account=self.user,
).select_related("banding_type_vocab")
}
else:
account_choices = {}

for banding_type in self.banding_types:
if banding_type.active:
session_string = "banding_type_{}".format(
banding_type.pk
)
choices = [["", "-----"]]
for vocab in banding_type.vocabs.all():
choices.append([vocab.pk, vocab.text])
self.fields[session_string] = forms.ChoiceField(
choices=choices,
label=banding_type.name,
)
if self.user:
account_banding_choice = account_choices.get(
banding_type.pk
)
self.fields[session_string].initial = (
account_banding_choice.banding_type_vocab.pk
if account_banding_choice
else None
)
else:
self.fields[session_string].initial = (
self.user_session.get(session_string, None)
)

self.fields[session_string].help_text = (
banding_type.description
)

self.helper.layout.append(
Layout(session_string),
)
if "currency" in self.changed_data:
self.fields[session_string].required = False

if "currency" in self.changed_data and self.fields.get("fte"):
self.fields["fte"].required = False

self.helper.layout.append(
Submit(
"fte_form",
"Update",
css_class="btn btn-primary btn-obc-blue",
),
)

def save(self) -> None:
for key, value in self.cleaned_data.items():
if self.user:
if key == "fte" and value:
self.user.profile.fte = value
elif key == "currency" and value:
self.user.profile.default_currency = value
elif value:
banding_type_pk = key.replace("banding_type_", "")
banding_type_vocab = vm.BandingVocab.objects.get(
pk=value,
)
accm.AccountBandingChoices.objects.update_or_create(
account=self.user,
banding_type_id=banding_type_pk,
defaults={
"banding_type_vocab": banding_type_vocab,
},
)
self.user.profile.save()
else:
if key == "fte":
self.user_session[key] = value
elif key == "currency":
self.user_session[key] = value.pk
else:
self.user_session[key] = value


class ManagePackageForm(forms.ModelForm):
"""
Form for managing packages
Expand Down
33 changes: 33 additions & 0 deletions src/package/migrations/0077_auto_20260208_1931.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
# Generated by Django 3.2.8 on 2026-02-08 19:31

from django.db import migrations, models


class Migration(migrations.Migration):

dependencies = [
('package', '0076_auto_20251020_1005'),
]

operations = [
migrations.AddIndex(
model_name='banding',
index=models.Index(fields=['package', 'banding_type'], name='banding_pkg_type_idx'),
),
migrations.AddIndex(
model_name='bandingtypecurrencyentry',
index=models.Index(fields=['package', 'banding_type_entry'], name='btce_pkg_bte_idx'),
),
migrations.AddIndex(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unsure how helpful this index will be, as the bandingtypeentry is probably shared by many rows

model_name='bandingtypeentry',
index=models.Index(fields=['package', 'banding_type'], name='bte_pkg_type_idx'),
),
migrations.AddIndex(
model_name='country',
index=models.Index(fields=['currency', 'catch_all'], name='country_currency_catchall_idx'),
),
migrations.AddIndex(
model_name='price',
index=models.Index(fields=['banding', 'country'], name='price_banding_country_idx'),
),
]
Loading