diff --git a/attendance/templates/attendance.html b/attendance/templates/attendance.html index a6873da..0ae039d 100644 --- a/attendance/templates/attendance.html +++ b/attendance/templates/attendance.html @@ -1,143 +1,104 @@ -{% extends "home/home.html" %} +{% extends "base.html" %} {% block content %} - - -
-
  • Home
  • -
    - -
    - {% if course %} -

    Attendance for {{ course }}

    - - - - - - - - {% for date in dates %} - - - - - - - {% endfor %} -
    DateDaily AttendanceTake AttendanceSend Absent Notifications
    {{ date }}{{ daily_attendance|get_item:date }}% -
    - {% csrf_token %} - - - - -
    -
    -
    - {% csrf_token %} - - - - -
    -
    - {% elif attendance_objects %} -

    {{ course_name }} {{ attendance_objects.first.date }}

    -
    - {% csrf_token %} - - - - - - - - {% for attendance_object in attendance_objects %} - - - - - - +
    +
    + {% if course %} +

    Attendance for {{ course }}

    +
    DateStudentStatusCurrent Status
    {{ attendance_object.date }}{{ attendance_object.student.first_name }} {{ attendance_object.student.last_name }} - - - {{ attendance_object.presence }} -
    + + + + + + + {% for date in dates %} + + + + + + {% endfor %}
    DateDaily AttendanceTake AttendanceSend Absent Notifications
    {{ date }}{{ daily_attendance|get_item:date }}% + View/Take + + + {% csrf_token %} + + + + + +
    - - - -
    - -
    - - {% else %} -

    Attendance Home

    - - - - - - - - {% for classroom in classrooms %} - - - - - - - {% endfor %} -
    CourseTeacherOverall AttendanceView Attendance
    {{ classroom.course }}{{ classroom.teacher }}{{ attendance_averages|get_item:classroom.course }}% -
    - -
    -
    - {% endif %} + {% elif attendance_objects %} +

    {{ course_name }} {{ attendance_objects.first.date }}

    +
    + {% csrf_token %} + + + + + + + + {% for attendance_object in attendance_objects %} + + + + + + + {% endfor %} +
    DateStudentStatusCurrent Status
    {{ attendance_object.date }}{{ attendance_object.student.first_name }} {{ attendance_object.student.last_name }} +
    + +
    +
    + {{ attendance_object.presence }} +
    + + + +
    + +
    +
    + {% else %} +

    Attendance Home

    + + + + + + + {% for classroom in classrooms %} + + + + + + {% endfor %} +
    CourseOverall AttendanceView Attendance
    {{ classroom.course }}{{ attendance_averages|get_item:classroom.course }}% +
    + +
    +
    + {% endif %} +
    + {% endblock content %} + + diff --git a/attendance/templates/attendance_base.html b/attendance/templates/attendance_base.html new file mode 100644 index 0000000..807ddec --- /dev/null +++ b/attendance/templates/attendance_base.html @@ -0,0 +1,40 @@ + +{% load static %} + + + + + + + + + + + + + Mission Bit + {% include "manipulation_js.html" %} + + + + + {% include 'header.html' %} + + {% include 'instafeed.html' %} + + {% include 'left_side_panel.html' %} + +
    +
    +
    +
    + {% block content %} + + {% endblock %} +
    +
    + + {% include 'footer.html' %} + + + diff --git a/attendance/urls.py b/attendance/urls.py index 7f49511..cf2af15 100644 --- a/attendance/urls.py +++ b/attendance/urls.py @@ -3,6 +3,14 @@ urlpatterns = [ path("", views.attendance, name="attendance"), - path("take_attendance/", views.take_attendance, name="take_attendance"), - path("notify_absent_students/", views.notify_absent_students, name="notify_absent_students") + path( + "take_attendance///", + views.take_attendance, + name="take_attendance", + ), + path( + "notify_absent_students/", + views.notify_absent_students, + name="notify_absent_students", + ), ] diff --git a/attendance/views.py b/attendance/views.py index 628bad0..2cab106 100644 --- a/attendance/views.py +++ b/attendance/views.py @@ -17,6 +17,7 @@ @group_required_multiple(["staff", "teacher"]) def attendance(request): + user_group = request.user.groups.first() if request.method == "POST": store_attendance_data(request) async_task( @@ -28,23 +29,24 @@ def attendance(request): course_id = request.GET.get("course_id") context = get_classroom_attendance(course_id) context.update( - {"attendance_statistic": get_course_attendance_statistic(course_id)} + { + "attendance_statistic": get_course_attendance_statistic(course_id), + "user_group": str(user_group), + } ) else: attendance_averages = compile_attendance_averages_for_all_courses() context = { "classrooms": Classroom.objects.all(), "attendance_averages": attendance_averages, + "user_group": str(user_group), } return render(request, "attendance.html", context) @group_required_multiple(["staff", "teacher"]) -def take_attendance(request): - context = take_attendance_context( - request.GET.get("course_id"), - get_date_from_template_returned_string(request.GET.get("date")), - ) +def take_attendance(request, course_id, date): + context = take_attendance_context(course_id, date) return render(request, "attendance.html", context) @@ -53,10 +55,14 @@ def notify_absent_students(request): # This method is a candidate for an async_task date = get_date_from_template_returned_string(request.GET.get("date")) course = Classroom.objects.get(id=request.GET.get("course_id")) - absences = Attendance.objects.filter(date=date, classroom_id=course.id, presence="Absent") - student_list = list(DjangoUser.objects.filter(id__in=[absence.student_id for absence in absences])) - create_absence_notifications(request, student_list, absences, date) - messages.add_message(request, messages.SUCCESS, "Absent Students Successfully Notified") + absences = Attendance.objects.filter( + date=date, classroom_id=course.id, presence="Absent" + ).select_related("student") + # student_list = list(DjangoUser.objects.filter(id__in=[absence.student_id for absence in absences])) + create_absence_notifications(request, absences, date) + messages.add_message( + request, messages.SUCCESS, "Absent Students Successfully Notified" + ) return redirect("attendance") @@ -113,9 +119,10 @@ def compile_daily_attendance_for_course(course_id): def get_average_attendance_from_list(daily_attendance): - attendance_list = [attendance_object.presence == "Present" - or attendance_object.presence == "Late" - for attendance_object in daily_attendance] + attendance_list = [ + attendance_object.presence in ("Present", "Late") + for attendance_object in daily_attendance + ] return statistics.mean(attendance_list) if len(attendance_list) > 0 else 0 @@ -136,7 +143,9 @@ def get_date_from_template_returned_string(string_date): return datetime.strptime(string_date, date_format).date() except ValueError: pass - raise ValueError("time data {!r} does not match any expected date format".format(string_date)) + raise ValueError( + "time data {!r} does not match any expected date format".format(string_date) + ) def update_course_attendance_statistic(course_id): @@ -155,17 +164,22 @@ def get_course_attendance_statistic(course_id): ) -def create_absence_notifications(request, student_list, absences, date): - notifications = [Notification( - subject="%s %s absence on %s" % (student.first_name, student.last_name, date), - notification=get_generic_absence_notification(student, date), - user_id=student.id, - attendance_id=absences[x].id, - created_by=DjangoUser.objects.get(id=request.user.id), - email_recipients=True - ) for x, student in enumerate(student_list)] +def create_absence_notifications(request, absences, date): + django_user = DjangoUser.objects.get(id=request.user.id) + notifications = [ + Notification( + subject="%s %s absence on %s" + % (absence.student.first_name, absence.student.last_name, date), + notification=get_generic_absence_notification(absence.student, date), + user_id=absence.student.id, + attendance_id=absence.id, + created_by=django_user, + email_recipients=True, + ) + for absence in absences + ] Notification.objects.bulk_create(notifications) - email_absence_notifications(request, student_list, date) + email_absence_notifications(request, absences, date) def email_absence_notifications(request, email_list, date): @@ -179,11 +193,8 @@ def email_absence_notifications(request, email_list, date): }, ) text_content = "You are being notified about something" - recipient_list = [ - "tyler.iams@gmail.com", - "iams.sophia@gmail.com", - ] - # Will replace with [user.email for user in email_list] + recipient_list = ["tyler.iams@gmail.com", "iams.sophia@gmail.com"] + # Will replace with [absence.student.email for user in email_list] email = EmailMultiAlternatives( subject, text_content, settings.EMAIL_HOST_USER, recipient_list ) diff --git a/context_processors.py b/context_processors.py new file mode 100644 index 0000000..4f6011f --- /dev/null +++ b/context_processors.py @@ -0,0 +1,11 @@ +from staff.staff_views_helper import get_classroom_by_django_user + + +def user_groups(request): + user_groups = set(request.user.groups.all().values_list("name", flat=True)) + return {"user_groups": user_groups} + + +def user_classroom(request): + classroom = get_classroom_by_django_user(request.user) + return {"classroom": classroom} diff --git a/donor/templates/donor.html b/donor/templates/donor.html index f40ff4f..8139ead 100644 --- a/donor/templates/donor.html +++ b/donor/templates/donor.html @@ -1,4 +1,4 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} {% block content %} diff --git a/home/apps.py b/home/apps.py index ddcd471..8eb58ca 100644 --- a/home/apps.py +++ b/home/apps.py @@ -2,19 +2,21 @@ from django.db.models.signals import pre_migrate from azure.storage.blob import PublicAccess + def ensure_azure_container(sender, **kwargs): """ Ensure that the expected Azure Storage container exists when running with an emulated service. """ from missionbit.azure_storage_backend import CustomAzureStorage + if not CustomAzureStorage.is_emulated: return CustomAzureStorage().service.create_container( - CustomAzureStorage.azure_container, - public_access=PublicAccess.Blob + CustomAzureStorage.azure_container, public_access=PublicAccess.Blob ) + class HomeConfig(AppConfig): name = "home" diff --git a/home/choices.py b/home/choices.py index 374d468..0b706a1 100644 --- a/home/choices.py +++ b/home/choices.py @@ -629,7 +629,9 @@ CHANGE_STUDENT_CHOICES = (("Add", "Add"), ("Remove", "Remove"), ("None", "None")) -CLASSROOM_MEMBERSHIP_CHOICES = (("teacher", "teacher"), - ("teacher_assistant", "teacher_assistant"), - ("student", "student"), - ("volunteer", "volunteer")) +CLASSROOM_MEMBERSHIP_CHOICES = ( + ("teacher", "teacher"), + ("teacher_assistant", "teacher_assistant"), + ("student", "student"), + ("volunteer", "volunteer"), +) diff --git a/home/forms.py b/home/forms.py index 04cbf06..a529446 100644 --- a/home/forms.py +++ b/home/forms.py @@ -2,7 +2,16 @@ from django.contrib.auth.forms import UserCreationForm, PasswordChangeForm from django.contrib.auth.models import User as DjangoUser from django.contrib.auth.models import Group -from home.models.models import Announcement, Classroom, Form, Esign, FormDistribution, Notification, Session, Resource, ClassroomMembership +from home.models.models import ( + Announcement, + Classroom, + Form, + Esign, + FormDistribution, + Notification, + Session, + Resource, +) from home.models.salesforce import ( Contact, User, @@ -13,26 +22,9 @@ from home.choices import * -class UserRegisterForm(UserCreationForm): - username = forms.CharField(label="Choose Username", max_length=100) - email = forms.EmailField(label="email", max_length=100) - first_name = forms.CharField(label="First name", max_length=100) - last_name = forms.CharField(label="Last name", max_length=100) - - class Meta: - model = DjangoUser - fields = [ - "username", - "email", - "first_name", - "last_name", - "password1", - "password2", - ] - - class DateInput(forms.DateInput): input_type = "date" + is_required = True class MissionBitUserCreationForm(forms.ModelForm): @@ -44,11 +36,7 @@ class MissionBitUserCreationForm(forms.ModelForm): class Meta: model = Contact - fields = ["account", - "first_name", - "last_name", - "email", - "owner"] + fields = ["account", "first_name", "last_name", "email", "owner"] class RaceGenderEthnicityForm(forms.ModelForm): @@ -67,6 +55,49 @@ class Meta: fields = [] +class ContactRegisterForm(forms.Form): + birthdate = forms.DateField(widget=DateInput) + expected_graduation_year = forms.ChoiceField( + label="Expected graduation year", choices=GRAD_YEAR_CHOICES, required=False + ) + which_best_describes_your_ethnicity = forms.ChoiceField( + label="Ethnicity - Optional", choices=ETHNICITY_CHOICES, required=False + ) + race = forms.ChoiceField( + label="Race - Optional", choices=RACE_CHOICES, required=False + ) + gender = forms.ChoiceField( + label="Gender - Optional", choices=GENDER_CHOICES, required=False + ) + + class Meta: + fields = [ + "birthdate", + "which_best_describes_your_ethnicity", + "race", + "gender", + "expected_graduation_year", + ] + + +class UserRegisterForm(UserCreationForm): + username = forms.CharField(label="Choose Username", max_length=100) + email = forms.EmailField(label="email", max_length=100) + first_name = forms.CharField(label="First name", max_length=100) + last_name = forms.CharField(label="Last name", max_length=100) + + class Meta: + model = DjangoUser + fields = [ + "username", + "email", + "first_name", + "last_name", + "password1", + "password2", + ] + + class CreateStaffForm(MissionBitUserCreationForm): title = forms.CharField(initial="Staff", disabled=True) @@ -81,9 +112,7 @@ class Meta: "owner", "title", ] - widgets = { - "birthdate": DateInput() - } + widgets = {"birthdate": DateInput()} class CreateStudentForm(RaceGenderEthnicityForm, MissionBitUserCreationForm): @@ -107,9 +136,7 @@ class Meta: "race", "gender", ] - widgets = { - "birthdate": DateInput() - } + widgets = {"birthdate": DateInput()} class CreateTeacherForm(RaceGenderEthnicityForm, MissionBitUserCreationForm): @@ -129,9 +156,7 @@ class Meta: "race", "gender", ] - widgets = { - "birthdate": DateInput() - } + widgets = {"birthdate": DateInput()} class CreateVolunteerForm(RaceGenderEthnicityForm, MissionBitUserCreationForm): @@ -151,9 +176,7 @@ class Meta: "race", "gender", ] - widgets = { - "birthdate": DateInput() - } + widgets = {"birthdate": DateInput()} class CreateClassroomForm(forms.ModelForm): @@ -203,10 +226,7 @@ class Meta: "instructor", "meeting_days", ] - widgets = { - "start_date": DateInput(), - "end_date": DateInput() - } + widgets = {"start_date": DateInput(), "end_date": DateInput()} def __str__(self): return "%s" % self.name @@ -316,10 +336,7 @@ class CreateEsignForm(forms.Form): class Meta: model = Esign - fields = [ - "name", - "link" - ] + fields = ["name", "link"] class CollectForms(forms.ModelForm): @@ -327,9 +344,7 @@ class CollectForms(forms.ModelForm): class Meta: model = FormDistribution - fields = [ - "submitted" - ] + fields = ["submitted"] class NotifyUnsubmittedUsersForm(forms.ModelForm): @@ -339,16 +354,14 @@ class NotifyUnsubmittedUsersForm(forms.ModelForm): class Meta: model = Notification - fields = [ - "subject", - "notification", - "email_recipients", - ] + fields = ["subject", "notification", "email_recipients"] class AddCurriculumForm(forms.ModelForm): title = forms.CharField(max_length=240, required=False) - description = forms.CharField(max_length=2000, required=False, widget=forms.Textarea) + description = forms.CharField( + max_length=2000, required=False, widget=forms.Textarea + ) lesson_plan = forms.FileField(required=False) lecture = forms.FileField(required=False) video = forms.URLField(required=False) @@ -356,14 +369,7 @@ class AddCurriculumForm(forms.ModelForm): class Meta: model = Session - fields = [ - "title", - "description", - "lesson_plan", - "lecture", - "video", - "activity" - ] + fields = ["title", "description", "lesson_plan", "lecture", "video", "activity"] class AddResourceForm(forms.ModelForm): @@ -374,12 +380,7 @@ class AddResourceForm(forms.ModelForm): class Meta: model = Resource - fields = [ - "title", - "description", - "link", - "file" - ] + fields = ["title", "description", "link", "file"] class AddForumForm(forms.ModelForm): @@ -388,7 +389,4 @@ class AddForumForm(forms.ModelForm): class Meta: model = Classroom - fields = [ - "forum_title", - "forum", - ] + fields = ["forum_title", "forum"] diff --git a/home/generic_notifications.py b/home/generic_notifications.py index 35855d9..79a3cb8 100644 --- a/home/generic_notifications.py +++ b/home/generic_notifications.py @@ -1,3 +1,5 @@ def get_generic_absence_notification(student, date): - return "Hello, our records indicate that %s %s was absent on %s, " \ - "please advise." % (student.first_name, student.last_name, date) + return ( + "Hello, our records indicate that %s %s was absent on %s, " + "please advise." % (student.first_name, student.last_name, date) + ) diff --git a/home/migrations/0001_initial.py b/home/migrations/0001_initial.py index c2f7a19..064ca3f 100644 --- a/home/migrations/0001_initial.py +++ b/home/migrations/0001_initial.py @@ -7,367 +7,2579 @@ import salesforce.backend.operations import salesforce.fields + class Migration(migrations.Migration): initial = True dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('auth', '0011_update_proxy_permissions'), + ("auth", "0011_update_proxy_permissions"), ] operations = [ migrations.CreateModel( - name='Account', + name="Account", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('is_deleted', salesforce.fields.BooleanField(default=False, verbose_name='Deleted')), - ('name', salesforce.fields.CharField(max_length=255, verbose_name='Account Name')), - ('type', salesforce.fields.CharField(blank=True, choices=[('School', 'School'), ('Foundation', 'Foundation'), ('Government', 'Government'), ('Business', 'Business'), ('Nonprofit', 'Nonprofit')], max_length=40, null=True, verbose_name='Account Type')), - ('billing_street', salesforce.fields.TextField(blank=True, null=True)), - ('billing_city', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('billing_state', salesforce.fields.CharField(blank=True, max_length=80, null=True, verbose_name='Billing State/Province')), - ('billing_postal_code', salesforce.fields.CharField(blank=True, max_length=20, null=True, verbose_name='Billing Zip/Postal Code')), - ('billing_country', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('npe01_systemis_individual', salesforce.fields.BooleanField(db_column='npe01__SYSTEMIsIndividual__c', default=salesforce.backend.operations.DefaultedOnCreate(), help_text='Indicates whether or not this Account is special for Contacts (Household, One-to-One, Individual) vs a normal Account.', verbose_name='_SYSTEM: IsIndividual')), - ('master_record', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='account_masterrecord_set', to='home.Account')), - ('parent', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='account_parent_set', to='home.Account')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_deleted", + salesforce.fields.BooleanField( + default=False, verbose_name="Deleted" + ), + ), + ( + "name", + salesforce.fields.CharField( + max_length=255, verbose_name="Account Name" + ), + ), + ( + "type", + salesforce.fields.CharField( + blank=True, + choices=[ + ("School", "School"), + ("Foundation", "Foundation"), + ("Government", "Government"), + ("Business", "Business"), + ("Nonprofit", "Nonprofit"), + ], + max_length=40, + null=True, + verbose_name="Account Type", + ), + ), + ("billing_street", salesforce.fields.TextField(blank=True, null=True)), + ( + "billing_city", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "billing_state", + salesforce.fields.CharField( + blank=True, + max_length=80, + null=True, + verbose_name="Billing State/Province", + ), + ), + ( + "billing_postal_code", + salesforce.fields.CharField( + blank=True, + max_length=20, + null=True, + verbose_name="Billing Zip/Postal Code", + ), + ), + ( + "billing_country", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "npe01_systemis_individual", + salesforce.fields.BooleanField( + db_column="npe01__SYSTEMIsIndividual__c", + default=salesforce.backend.operations.DefaultedOnCreate(), + help_text="Indicates whether or not this Account is special for Contacts (Household, One-to-One, Individual) vs a normal Account.", + verbose_name="_SYSTEM: IsIndividual", + ), + ), + ( + "master_record", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="account_masterrecord_set", + to="home.Account", + ), + ), + ( + "parent", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="account_parent_set", + to="home.Account", + ), + ), ], options={ - 'verbose_name': 'Account', - 'verbose_name_plural': 'Accounts', - 'db_table': 'Account', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "Account", + "verbose_name_plural": "Accounts", + "db_table": "Account", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.CreateModel( - name='Attendance', + name="Attendance", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('date', models.DateField(default='1901-01-01')), - ('presence', models.CharField(default='Unassigned', max_length=100)), - ('notes', models.TextField(default='', max_length=500)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("date", models.DateField(default="1901-01-01")), + ("presence", models.CharField(default="Unassigned", max_length=100)), + ("notes", models.TextField(default="", max_length=500)), ], ), migrations.CreateModel( - name='Classroom', + name="Classroom", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('course', models.CharField(choices=[('Android Game Design', 'Android Game Design'), ('Intro to Web Programming', 'Intro to Web Programming'), ('Field Trips', 'Field Trips'), ('Intro to Game Design with Unity', 'Intro to Game Design with Unity'), ('Web Design 101', 'Web Design 101'), ('Mobile App Dev with Ionic', 'Mobile App Dev with Ionic'), ('MB Internship', 'MB Internship'), ('Structured Study Program', 'Structured Study Program')], max_length=255)), - ('attendance_summary', django.contrib.postgres.fields.jsonb.JSONField(default=None, null=True)), - ('students', models.ManyToManyField(related_name='classroom_students', to=settings.AUTH_USER_MODEL)), - ('teacher', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='classroom_lead_teacher', to=settings.AUTH_USER_MODEL)), - ('teacher_assistant', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='classroom_teacher_assistant', to=settings.AUTH_USER_MODEL)), - ('volunteers', models.ManyToManyField(related_name='classroom_volunteers', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "course", + models.CharField( + choices=[ + ("Android Game Design", "Android Game Design"), + ("Intro to Web Programming", "Intro to Web Programming"), + ("Field Trips", "Field Trips"), + ( + "Intro to Game Design with Unity", + "Intro to Game Design with Unity", + ), + ("Web Design 101", "Web Design 101"), + ("Mobile App Dev with Ionic", "Mobile App Dev with Ionic"), + ("MB Internship", "MB Internship"), + ("Structured Study Program", "Structured Study Program"), + ], + max_length=255, + ), + ), + ( + "attendance_summary", + django.contrib.postgres.fields.jsonb.JSONField( + default=None, null=True + ), + ), + ( + "students", + models.ManyToManyField( + related_name="classroom_students", to=settings.AUTH_USER_MODEL + ), + ), + ( + "teacher", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="classroom_lead_teacher", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "teacher_assistant", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="classroom_teacher_assistant", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "volunteers", + models.ManyToManyField( + related_name="classroom_volunteers", to=settings.AUTH_USER_MODEL + ), + ), ], ), migrations.CreateModel( - name='Esign', + name="Esign", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=240, unique=True)), - ('template', models.URLField()), - ('created_by', models.ForeignKey(default=False, on_delete=django.db.models.deletion.CASCADE, related_name='esign_creator_user', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=240, unique=True)), + ("template", models.URLField()), + ( + "created_by", + models.ForeignKey( + default=False, + on_delete=django.db.models.deletion.CASCADE, + related_name="esign_creator_user", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Form', + name="Form", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('name', models.CharField(max_length=240, unique=True)), - ('description', models.TextField(max_length=2500)), - ('form', models.FileField(upload_to='documents/')), - ('posted', models.DateTimeField(auto_now=True, db_index=True)), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_user', to=settings.AUTH_USER_MODEL)), - ('esign', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='esign_form', to='home.Esign')), - ('recipient_classrooms', models.ManyToManyField(related_name='form_recipient_classroom', to='home.Classroom')), - ('recipient_groups', models.ManyToManyField(related_name='form_user_groups', to='auth.Group')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("name", models.CharField(max_length=240, unique=True)), + ("description", models.TextField(max_length=2500)), + ("form", models.FileField(upload_to="documents/")), + ("posted", models.DateTimeField(auto_now=True, db_index=True)), + ( + "created_by", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="form_user", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "esign", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="esign_form", + to="home.Esign", + ), + ), + ( + "recipient_classrooms", + models.ManyToManyField( + related_name="form_recipient_classroom", to="home.Classroom" + ), + ), + ( + "recipient_groups", + models.ManyToManyField( + related_name="form_user_groups", to="auth.Group" + ), + ), ], ), migrations.CreateModel( - name='Session', + name="Session", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('description', models.TextField(default='No Description Available', max_length=2000)), - ('lesson_plan', models.FileField(default=None, upload_to='')), - ('lecture', models.FileField(default=None, upload_to='')), - ('video', models.URLField(default=None, null=True)), - ('activity', models.FileField(default=None, upload_to='')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "description", + models.TextField( + default="No Description Available", max_length=2000 + ), + ), + ("lesson_plan", models.FileField(default=None, upload_to="")), + ("lecture", models.FileField(default=None, upload_to="")), + ("video", models.URLField(default=None, null=True)), + ("activity", models.FileField(default=None, upload_to="")), ], ), migrations.CreateModel( - name='User', + name="User", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('username', salesforce.fields.CharField(max_length=80)), - ('last_name', salesforce.fields.CharField(max_length=80)), - ('first_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('middle_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('suffix', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('name', salesforce.fields.CharField(max_length=121, verbose_name='Full Name')), - ('company_name', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('division', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('department', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('title', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('street', salesforce.fields.TextField(blank=True, null=True)), - ('city', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('state', salesforce.fields.CharField(blank=True, max_length=80, null=True, verbose_name='State/Province')), - ('postal_code', salesforce.fields.CharField(blank=True, max_length=20, null=True, verbose_name='Zip/Postal Code')), - ('country', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('is_active', salesforce.fields.BooleanField(default=salesforce.backend.operations.DefaultedOnCreate(), verbose_name='Active')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("username", salesforce.fields.CharField(max_length=80)), + ("last_name", salesforce.fields.CharField(max_length=80)), + ( + "first_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "middle_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "suffix", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "name", + salesforce.fields.CharField( + max_length=121, verbose_name="Full Name" + ), + ), + ( + "company_name", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "division", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "department", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "title", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ("street", salesforce.fields.TextField(blank=True, null=True)), + ( + "city", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "state", + salesforce.fields.CharField( + blank=True, + max_length=80, + null=True, + verbose_name="State/Province", + ), + ), + ( + "postal_code", + salesforce.fields.CharField( + blank=True, + max_length=20, + null=True, + verbose_name="Zip/Postal Code", + ), + ), + ( + "country", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "is_active", + salesforce.fields.BooleanField( + default=salesforce.backend.operations.DefaultedOnCreate(), + verbose_name="Active", + ), + ), ], options={ - 'verbose_name': 'User', - 'verbose_name_plural': 'Users', - 'db_table': 'User', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "User", + "verbose_name_plural": "Users", + "db_table": "User", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.CreateModel( - name='UserProfile', + name="UserProfile", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('change_pwd', models.BooleanField(default=False)), - ('date_of_birth', models.DateField(default='1901-01-01')), - ('salesforce_id', models.CharField(default='xxxxxx19010101', max_length=14)), - ('user', models.OneToOneField(on_delete=django.db.models.deletion.CASCADE, to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("change_pwd", models.BooleanField(default=False)), + ("date_of_birth", models.DateField(default="1901-01-01")), + ( + "salesforce_id", + models.CharField(default="xxxxxx19010101", max_length=14), + ), + ( + "user", + models.OneToOneField( + on_delete=django.db.models.deletion.CASCADE, + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Notification', + name="Notification", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('subject', models.CharField(max_length=240)), - ('notification', models.TextField(max_length=2500)), - ('email_recipients', models.BooleanField(default=False)), - ('notified', models.DateTimeField(auto_now=True, db_index=True)), - ('acknowledged', models.BooleanField(default=False)), - ('attendance', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notified_about_attendance', to='home.Attendance')), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notification_user', to=settings.AUTH_USER_MODEL)), - ('form', models.ForeignKey(null=True, on_delete=django.db.models.deletion.CASCADE, related_name='notified_about_form', to='home.Form')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='notified_user', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("subject", models.CharField(max_length=240)), + ("notification", models.TextField(max_length=2500)), + ("email_recipients", models.BooleanField(default=False)), + ("notified", models.DateTimeField(auto_now=True, db_index=True)), + ("acknowledged", models.BooleanField(default=False)), + ( + "attendance", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="notified_about_attendance", + to="home.Attendance", + ), + ), + ( + "created_by", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="notification_user", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "form", + models.ForeignKey( + null=True, + on_delete=django.db.models.deletion.CASCADE, + related_name="notified_about_form", + to="home.Form", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="notified_user", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Individual', + name="Individual", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('is_deleted', salesforce.fields.BooleanField(default=False, verbose_name='Deleted')), - ('last_name', salesforce.fields.CharField(max_length=80)), - ('first_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('salutation', salesforce.fields.CharField(blank=True, choices=[('Mr.', 'Mr.'), ('Ms.', 'Ms.'), ('Mrs.', 'Mrs.'), ('Dr.', 'Dr.'), ('Prof.', 'Prof.')], max_length=40, null=True)), - ('middle_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('suffix', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('name', salesforce.fields.CharField(max_length=121)), - ('owner', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='individual_owner_set', to='home.User')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_deleted", + salesforce.fields.BooleanField( + default=False, verbose_name="Deleted" + ), + ), + ("last_name", salesforce.fields.CharField(max_length=80)), + ( + "first_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "salutation", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Mr.", "Mr."), + ("Ms.", "Ms."), + ("Mrs.", "Mrs."), + ("Dr.", "Dr."), + ("Prof.", "Prof."), + ], + max_length=40, + null=True, + ), + ), + ( + "middle_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "suffix", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ("name", salesforce.fields.CharField(max_length=121)), + ( + "owner", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="individual_owner_set", + to="home.User", + ), + ), ], options={ - 'verbose_name': 'Individual', - 'verbose_name_plural': 'Individuals', - 'db_table': 'Individual', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "Individual", + "verbose_name_plural": "Individuals", + "db_table": "Individual", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.CreateModel( - name='FormDistribution', + name="FormDistribution", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('submitted', models.BooleanField(default=False)), - ('form', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_to_be_signed', to='home.Form')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='form_signer', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("submitted", models.BooleanField(default=False)), + ( + "form", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="form_to_be_signed", + to="home.Form", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="form_signer", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.CreateModel( - name='Contact', + name="Contact", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('is_deleted', salesforce.fields.BooleanField(default=False, verbose_name='Deleted')), - ('last_name', salesforce.fields.CharField(max_length=80)), - ('first_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('salutation', salesforce.fields.CharField(blank=True, choices=[('Mr.', 'Mr.'), ('Ms.', 'Ms.'), ('Mrs.', 'Mrs.'), ('Dr.', 'Dr.'), ('Prof.', 'Prof.')], max_length=40, null=True)), - ('middle_name', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('suffix', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('name', salesforce.fields.CharField(max_length=121, verbose_name='Full Name')), - ('mailing_street', salesforce.fields.TextField(blank=True, null=True)), - ('mailing_city', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('mailing_state', salesforce.fields.CharField(blank=True, max_length=80, null=True, verbose_name='Mailing State/Province')), - ('mailing_postal_code', salesforce.fields.CharField(blank=True, max_length=20, null=True, verbose_name='Mailing Zip/Postal Code')), - ('mailing_country', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('mailing_state_code', salesforce.fields.CharField(blank=True, choices=[('AC', 'Acre'), ('AG', 'Agrigento'), ('AG', 'Aguascalientes'), ('AL', 'Alabama'), ('AL', 'Alagoas'), ('AK', 'Alaska'), ('AB', 'Alberta'), ('AL', 'Alessandria'), ('AP', 'Amapá'), ('AM', 'Amazonas'), ('AN', 'Ancona'), ('AN', 'Andaman and Nicobar Islands'), ('AP', 'Andhra Pradesh'), ('34', 'Anhui'), ('AO', 'Aosta'), ('AR', 'Arezzo'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AR', 'Arunachal Pradesh'), ('AP', 'Ascoli Piceno'), ('AS', 'Assam'), ('AT', 'Asti'), ('ACT', 'Australian Capital Territory'), ('AV', 'Avellino'), ('BA', 'Bahia'), ('BC', 'Baja California'), ('BS', 'Baja California Sur'), ('BA', 'Bari'), ('BT', 'Barletta-Andria-Trani'), ('11', 'Beijing'), ('BL', 'Belluno'), ('BN', 'Benevento'), ('BG', 'Bergamo'), ('BI', 'Biella'), ('BR', 'Bihar'), ('BO', 'Bologna'), ('BZ', 'Bolzano'), ('BS', 'Brescia'), ('BR', 'Brindisi'), ('BC', 'British Columbia'), ('CA', 'Cagliari'), ('CA', 'California'), ('CL', 'Caltanissetta'), ('CM', 'Campeche'), ('CB', 'Campobasso'), ('CI', 'Carbonia-Iglesias'), ('CW', 'Carlow'), ('CE', 'Caserta'), ('CT', 'Catania'), ('CZ', 'Catanzaro'), ('CN', 'Cavan'), ('CE', 'Ceará'), ('CH', 'Chandigarh'), ('CT', 'Chhattisgarh'), ('CS', 'Chiapas'), ('CH', 'Chieti'), ('CH', 'Chihuahua'), ('71', 'Chinese Taipei'), ('50', 'Chongqing'), ('CE', 'Clare'), ('CO', 'Coahuila'), ('CL', 'Colima'), ('CO', 'Colorado'), ('CO', 'Como'), ('CT', 'Connecticut'), ('CO', 'Cork'), ('CS', 'Cosenza'), ('CR', 'Cremona'), ('KR', 'Crotone'), ('CN', 'Cuneo'), ('DN', 'Dadra and Nagar Haveli'), ('DD', 'Daman and Diu'), ('DE', 'Delaware'), ('DL', 'Delhi'), ('DC', 'District of Columbia'), ('DF', 'Distrito Federal'), ('DL', 'Donegal'), ('D', 'Dublin'), ('DG', 'Durango'), ('EN', 'Enna'), ('ES', 'Espírito Santo'), ('DF', 'Federal District'), ('FM', 'Fermo'), ('FE', 'Ferrara'), ('FI', 'Florence'), ('FL', 'Florida'), ('FG', 'Foggia'), ('FC', 'Forlì-Cesena'), ('FR', 'Frosinone'), ('35', 'Fujian'), ('G', 'Galway'), ('62', 'Gansu'), ('GE', 'Genoa'), ('GA', 'Georgia'), ('GA', 'Goa'), ('GO', 'Goiás'), ('GO', 'Gorizia'), ('GR', 'Grosseto'), ('GT', 'Guanajuato'), ('44', 'Guangdong'), ('45', 'Guangxi'), ('GR', 'Guerrero'), ('52', 'Guizhou'), ('GJ', 'Gujarat'), ('46', 'Hainan'), ('HR', 'Haryana'), ('HI', 'Hawaii'), ('13', 'Hebei'), ('23', 'Heilongjiang'), ('41', 'Henan'), ('HG', 'Hidalgo'), ('HP', 'Himachal Pradesh'), ('91', 'Hong Kong'), ('42', 'Hubei'), ('43', 'Hunan'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IM', 'Imperia'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('IS', 'Isernia'), ('JA', 'Jalisco'), ('JK', 'Jammu and Kashmir'), ('JH', 'Jharkhand'), ('32', 'Jiangsu'), ('36', 'Jiangxi'), ('22', 'Jilin'), ('KS', 'Kansas'), ('KA', 'Karnataka'), ('KY', 'Kentucky'), ('KL', 'Kerala'), ('KY', 'Kerry'), ('KE', 'Kildare'), ('KK', 'Kilkenny'), ('AQ', "L'Aquila"), ('LD', 'Lakshadweep'), ('LS', 'Laois'), ('SP', 'La Spezia'), ('LT', 'Latina'), ('LE', 'Lecce'), ('LC', 'Lecco'), ('LM', 'Leitrim'), ('21', 'Liaoning'), ('LK', 'Limerick'), ('LI', 'Livorno'), ('LO', 'Lodi'), ('LD', 'Longford'), ('LA', 'Louisiana'), ('LH', 'Louth'), ('LU', 'Lucca'), ('92', 'Macao'), ('MC', 'Macerata'), ('MP', 'Madhya Pradesh'), ('MH', 'Maharashtra'), ('ME', 'Maine'), ('MN', 'Manipur'), ('MB', 'Manitoba'), ('MN', 'Mantua'), ('MA', 'Maranhão'), ('MD', 'Maryland'), ('MS', 'Massa and Carrara'), ('MA', 'Massachusetts'), ('MT', 'Matera'), ('MT', 'Mato Grosso'), ('MS', 'Mato Grosso do Sul'), ('MO', 'Mayo'), ('MH', 'Meath'), ('VS', 'Medio Campidano'), ('ML', 'Meghalaya'), ('ME', 'Messina'), ('ME', 'Mexico State'), ('MI', 'Michigan'), ('MI', 'Michoacán'), ('MI', 'Milan'), ('MG', 'Minas Gerais'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MZ', 'Mizoram'), ('MO', 'Modena'), ('MN', 'Monaghan'), ('MT', 'Montana'), ('MB', 'Monza and Brianza'), ('MO', 'Morelos'), ('NL', 'Nagaland'), ('NA', 'Naples'), ('NA', 'Nayarit'), ('NE', 'Nebraska'), ('15', 'Nei Mongol'), ('NV', 'Nevada'), ('NB', 'New Brunswick'), ('NL', 'Newfoundland and Labrador'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NSW', 'New South Wales'), ('NY', 'New York'), ('64', 'Ningxia'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('NT', 'Northern Territory'), ('NT', 'Northwest Territories'), ('NO', 'Novara'), ('NS', 'Nova Scotia'), ('NL', 'Nuevo León'), ('NU', 'Nunavut'), ('NU', 'Nuoro'), ('OA', 'Oaxaca'), ('OR', 'Odisha'), ('OY', 'Offaly'), ('OG', 'Ogliastra'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OT', 'Olbia-Tempio'), ('ON', 'Ontario'), ('OR', 'Oregon'), ('OR', 'Oristano'), ('PD', 'Padua'), ('PA', 'Palermo'), ('PA', 'Pará'), ('PB', 'Paraíba'), ('PR', 'Paraná'), ('PR', 'Parma'), ('PV', 'Pavia'), ('PA', 'Pennsylvania'), ('PE', 'Pernambuco'), ('PG', 'Perugia'), ('PU', 'Pesaro and Urbino'), ('PE', 'Pescara'), ('PC', 'Piacenza'), ('PI', 'Piauí'), ('PI', 'Pisa'), ('PT', 'Pistoia'), ('PN', 'Pordenone'), ('PZ', 'Potenza'), ('PO', 'Prato'), ('PE', 'Prince Edward Island'), ('PY', 'Puducherry'), ('PB', 'Puebla'), ('PB', 'Punjab'), ('63', 'Qinghai'), ('QC', 'Quebec'), ('QLD', 'Queensland'), ('QE', 'Querétaro'), ('QR', 'Quintana Roo'), ('RG', 'Ragusa'), ('RJ', 'Rajasthan'), ('RA', 'Ravenna'), ('RC', 'Reggio Calabria'), ('RE', 'Reggio Emilia'), ('RI', 'Rhode Island'), ('RI', 'Rieti'), ('RN', 'Rimini'), ('RJ', 'Rio de Janeiro'), ('RN', 'Rio Grande do Norte'), ('RS', 'Rio Grande do Sul'), ('RM', 'Rome'), ('RO', 'Rondônia'), ('RR', 'Roraima'), ('RN', 'Roscommon'), ('RO', 'Rovigo'), ('SA', 'Salerno'), ('SL', 'San Luis Potosí'), ('SC', 'Santa Catarina'), ('SP', 'São Paulo'), ('SK', 'Saskatchewan'), ('SS', 'Sassari'), ('SV', 'Savona'), ('SE', 'Sergipe'), ('61', 'Shaanxi'), ('37', 'Shandong'), ('31', 'Shanghai'), ('14', 'Shanxi'), ('51', 'Sichuan'), ('SI', 'Siena'), ('SK', 'Sikkim'), ('SI', 'Sinaloa'), ('SO', 'Sligo'), ('SO', 'Sondrio'), ('SO', 'Sonora'), ('SA', 'South Australia'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('SR', 'Syracuse'), ('TB', 'Tabasco'), ('TM', 'Tamaulipas'), ('TN', 'Tamil Nadu'), ('TA', 'Taranto'), ('TAS', 'Tasmania'), ('TN', 'Tennessee'), ('TE', 'Teramo'), ('TR', 'Terni'), ('TX', 'Texas'), ('12', 'Tianjin'), ('TA', 'Tipperary'), ('TL', 'Tlaxcala'), ('TO', 'Tocantins'), ('TP', 'Trapani'), ('TN', 'Trento'), ('TV', 'Treviso'), ('TS', 'Trieste'), ('TR', 'Tripura'), ('TO', 'Turin'), ('UD', 'Udine'), ('UT', 'Utah'), ('UT', 'Uttarakhand'), ('UP', 'Uttar Pradesh'), ('VA', 'Varese'), ('VE', 'Venice'), ('VE', 'Veracruz'), ('VB', 'Verbano-Cusio-Ossola'), ('VC', 'Vercelli'), ('VT', 'Vermont'), ('VR', 'Verona'), ('VV', 'Vibo Valentia'), ('VI', 'Vicenza'), ('VIC', 'Victoria'), ('VA', 'Virginia'), ('VT', 'Viterbo'), ('WA', 'Washington'), ('WD', 'Waterford'), ('WB', 'West Bengal'), ('WA', 'Western Australia'), ('WH', 'Westmeath'), ('WV', 'West Virginia'), ('WX', 'Wexford'), ('WW', 'Wicklow'), ('WI', 'Wisconsin'), ('WY', 'Wyoming'), ('65', 'Xinjiang'), ('54', 'Xizang'), ('YU', 'Yucatán'), ('YT', 'Yukon Territories'), ('53', 'Yunnan'), ('ZA', 'Zacatecas'), ('33', 'Zhejiang')], max_length=10, null=True, verbose_name='Mailing State/Province Code')), - ('mailing_country_code', salesforce.fields.CharField(blank=True, choices=[('AC', 'Acre'), ('AG', 'Agrigento'), ('AG', 'Aguascalientes'), ('AL', 'Alabama'), ('AL', 'Alagoas'), ('AK', 'Alaska'), ('AB', 'Alberta'), ('AL', 'Alessandria'), ('AP', 'Amapá'), ('AM', 'Amazonas'), ('AN', 'Ancona'), ('AN', 'Andaman and Nicobar Islands'), ('AP', 'Andhra Pradesh'), ('34', 'Anhui'), ('AO', 'Aosta'), ('AR', 'Arezzo'), ('AZ', 'Arizona'), ('AR', 'Arkansas'), ('AR', 'Arunachal Pradesh'), ('AP', 'Ascoli Piceno'), ('AS', 'Assam'), ('AT', 'Asti'), ('ACT', 'Australian Capital Territory'), ('AV', 'Avellino'), ('BA', 'Bahia'), ('BC', 'Baja California'), ('BS', 'Baja California Sur'), ('BA', 'Bari'), ('BT', 'Barletta-Andria-Trani'), ('11', 'Beijing'), ('BL', 'Belluno'), ('BN', 'Benevento'), ('BG', 'Bergamo'), ('BI', 'Biella'), ('BR', 'Bihar'), ('BO', 'Bologna'), ('BZ', 'Bolzano'), ('BS', 'Brescia'), ('BR', 'Brindisi'), ('BC', 'British Columbia'), ('CA', 'Cagliari'), ('CA', 'California'), ('CL', 'Caltanissetta'), ('CM', 'Campeche'), ('CB', 'Campobasso'), ('CI', 'Carbonia-Iglesias'), ('CW', 'Carlow'), ('CE', 'Caserta'), ('CT', 'Catania'), ('CZ', 'Catanzaro'), ('CN', 'Cavan'), ('CE', 'Ceará'), ('CH', 'Chandigarh'), ('CT', 'Chhattisgarh'), ('CS', 'Chiapas'), ('CH', 'Chieti'), ('CH', 'Chihuahua'), ('71', 'Chinese Taipei'), ('50', 'Chongqing'), ('CE', 'Clare'), ('CO', 'Coahuila'), ('CL', 'Colima'), ('CO', 'Colorado'), ('CO', 'Como'), ('CT', 'Connecticut'), ('CO', 'Cork'), ('CS', 'Cosenza'), ('CR', 'Cremona'), ('KR', 'Crotone'), ('CN', 'Cuneo'), ('DN', 'Dadra and Nagar Haveli'), ('DD', 'Daman and Diu'), ('DE', 'Delaware'), ('DL', 'Delhi'), ('DC', 'District of Columbia'), ('DF', 'Distrito Federal'), ('DL', 'Donegal'), ('D', 'Dublin'), ('DG', 'Durango'), ('EN', 'Enna'), ('ES', 'Espírito Santo'), ('DF', 'Federal District'), ('FM', 'Fermo'), ('FE', 'Ferrara'), ('FI', 'Florence'), ('FL', 'Florida'), ('FG', 'Foggia'), ('FC', 'Forlì-Cesena'), ('FR', 'Frosinone'), ('35', 'Fujian'), ('G', 'Galway'), ('62', 'Gansu'), ('GE', 'Genoa'), ('GA', 'Georgia'), ('GA', 'Goa'), ('GO', 'Goiás'), ('GO', 'Gorizia'), ('GR', 'Grosseto'), ('GT', 'Guanajuato'), ('44', 'Guangdong'), ('45', 'Guangxi'), ('GR', 'Guerrero'), ('52', 'Guizhou'), ('GJ', 'Gujarat'), ('46', 'Hainan'), ('HR', 'Haryana'), ('HI', 'Hawaii'), ('13', 'Hebei'), ('23', 'Heilongjiang'), ('41', 'Henan'), ('HG', 'Hidalgo'), ('HP', 'Himachal Pradesh'), ('91', 'Hong Kong'), ('42', 'Hubei'), ('43', 'Hunan'), ('ID', 'Idaho'), ('IL', 'Illinois'), ('IM', 'Imperia'), ('IN', 'Indiana'), ('IA', 'Iowa'), ('IS', 'Isernia'), ('JA', 'Jalisco'), ('JK', 'Jammu and Kashmir'), ('JH', 'Jharkhand'), ('32', 'Jiangsu'), ('36', 'Jiangxi'), ('22', 'Jilin'), ('KS', 'Kansas'), ('KA', 'Karnataka'), ('KY', 'Kentucky'), ('KL', 'Kerala'), ('KY', 'Kerry'), ('KE', 'Kildare'), ('KK', 'Kilkenny'), ('AQ', "L'Aquila"), ('LD', 'Lakshadweep'), ('LS', 'Laois'), ('SP', 'La Spezia'), ('LT', 'Latina'), ('LE', 'Lecce'), ('LC', 'Lecco'), ('LM', 'Leitrim'), ('21', 'Liaoning'), ('LK', 'Limerick'), ('LI', 'Livorno'), ('LO', 'Lodi'), ('LD', 'Longford'), ('LA', 'Louisiana'), ('LH', 'Louth'), ('LU', 'Lucca'), ('92', 'Macao'), ('MC', 'Macerata'), ('MP', 'Madhya Pradesh'), ('MH', 'Maharashtra'), ('ME', 'Maine'), ('MN', 'Manipur'), ('MB', 'Manitoba'), ('MN', 'Mantua'), ('MA', 'Maranhão'), ('MD', 'Maryland'), ('MS', 'Massa and Carrara'), ('MA', 'Massachusetts'), ('MT', 'Matera'), ('MT', 'Mato Grosso'), ('MS', 'Mato Grosso do Sul'), ('MO', 'Mayo'), ('MH', 'Meath'), ('VS', 'Medio Campidano'), ('ML', 'Meghalaya'), ('ME', 'Messina'), ('ME', 'Mexico State'), ('MI', 'Michigan'), ('MI', 'Michoacán'), ('MI', 'Milan'), ('MG', 'Minas Gerais'), ('MN', 'Minnesota'), ('MS', 'Mississippi'), ('MO', 'Missouri'), ('MZ', 'Mizoram'), ('MO', 'Modena'), ('MN', 'Monaghan'), ('MT', 'Montana'), ('MB', 'Monza and Brianza'), ('MO', 'Morelos'), ('NL', 'Nagaland'), ('NA', 'Naples'), ('NA', 'Nayarit'), ('NE', 'Nebraska'), ('15', 'Nei Mongol'), ('NV', 'Nevada'), ('NB', 'New Brunswick'), ('NL', 'Newfoundland and Labrador'), ('NH', 'New Hampshire'), ('NJ', 'New Jersey'), ('NM', 'New Mexico'), ('NSW', 'New South Wales'), ('NY', 'New York'), ('64', 'Ningxia'), ('NC', 'North Carolina'), ('ND', 'North Dakota'), ('NT', 'Northern Territory'), ('NT', 'Northwest Territories'), ('NO', 'Novara'), ('NS', 'Nova Scotia'), ('NL', 'Nuevo León'), ('NU', 'Nunavut'), ('NU', 'Nuoro'), ('OA', 'Oaxaca'), ('OR', 'Odisha'), ('OY', 'Offaly'), ('OG', 'Ogliastra'), ('OH', 'Ohio'), ('OK', 'Oklahoma'), ('OT', 'Olbia-Tempio'), ('ON', 'Ontario'), ('OR', 'Oregon'), ('OR', 'Oristano'), ('PD', 'Padua'), ('PA', 'Palermo'), ('PA', 'Pará'), ('PB', 'Paraíba'), ('PR', 'Paraná'), ('PR', 'Parma'), ('PV', 'Pavia'), ('PA', 'Pennsylvania'), ('PE', 'Pernambuco'), ('PG', 'Perugia'), ('PU', 'Pesaro and Urbino'), ('PE', 'Pescara'), ('PC', 'Piacenza'), ('PI', 'Piauí'), ('PI', 'Pisa'), ('PT', 'Pistoia'), ('PN', 'Pordenone'), ('PZ', 'Potenza'), ('PO', 'Prato'), ('PE', 'Prince Edward Island'), ('PY', 'Puducherry'), ('PB', 'Puebla'), ('PB', 'Punjab'), ('63', 'Qinghai'), ('QC', 'Quebec'), ('QLD', 'Queensland'), ('QE', 'Querétaro'), ('QR', 'Quintana Roo'), ('RG', 'Ragusa'), ('RJ', 'Rajasthan'), ('RA', 'Ravenna'), ('RC', 'Reggio Calabria'), ('RE', 'Reggio Emilia'), ('RI', 'Rhode Island'), ('RI', 'Rieti'), ('RN', 'Rimini'), ('RJ', 'Rio de Janeiro'), ('RN', 'Rio Grande do Norte'), ('RS', 'Rio Grande do Sul'), ('RM', 'Rome'), ('RO', 'Rondônia'), ('RR', 'Roraima'), ('RN', 'Roscommon'), ('RO', 'Rovigo'), ('SA', 'Salerno'), ('SL', 'San Luis Potosí'), ('SC', 'Santa Catarina'), ('SP', 'São Paulo'), ('SK', 'Saskatchewan'), ('SS', 'Sassari'), ('SV', 'Savona'), ('SE', 'Sergipe'), ('61', 'Shaanxi'), ('37', 'Shandong'), ('31', 'Shanghai'), ('14', 'Shanxi'), ('51', 'Sichuan'), ('SI', 'Siena'), ('SK', 'Sikkim'), ('SI', 'Sinaloa'), ('SO', 'Sligo'), ('SO', 'Sondrio'), ('SO', 'Sonora'), ('SA', 'South Australia'), ('SC', 'South Carolina'), ('SD', 'South Dakota'), ('SR', 'Syracuse'), ('TB', 'Tabasco'), ('TM', 'Tamaulipas'), ('TN', 'Tamil Nadu'), ('TA', 'Taranto'), ('TAS', 'Tasmania'), ('TN', 'Tennessee'), ('TE', 'Teramo'), ('TR', 'Terni'), ('TX', 'Texas'), ('12', 'Tianjin'), ('TA', 'Tipperary'), ('TL', 'Tlaxcala'), ('TO', 'Tocantins'), ('TP', 'Trapani'), ('TN', 'Trento'), ('TV', 'Treviso'), ('TS', 'Trieste'), ('TR', 'Tripura'), ('TO', 'Turin'), ('UD', 'Udine'), ('UT', 'Utah'), ('UT', 'Uttarakhand'), ('UP', 'Uttar Pradesh'), ('VA', 'Varese'), ('VE', 'Venice'), ('VE', 'Veracruz'), ('VB', 'Verbano-Cusio-Ossola'), ('VC', 'Vercelli'), ('VT', 'Vermont'), ('VR', 'Verona'), ('VV', 'Vibo Valentia'), ('VI', 'Vicenza'), ('VIC', 'Victoria'), ('VA', 'Virginia'), ('VT', 'Viterbo'), ('WA', 'Washington'), ('WD', 'Waterford'), ('WB', 'West Bengal'), ('WA', 'Western Australia'), ('WH', 'Westmeath'), ('WV', 'West Virginia'), ('WX', 'Wexford'), ('WW', 'Wicklow'), ('WI', 'Wisconsin'), ('WY', 'Wyoming'), ('65', 'Xinjiang'), ('54', 'Xizang'), ('YU', 'Yucatán'), ('YT', 'Yukon Territories'), ('53', 'Yunnan'), ('ZA', 'Zacatecas'), ('33', 'Zhejiang')], default=salesforce.backend.operations.DefaultedOnCreate(), max_length=10, null=True)), - ('mobile_phone', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('home_phone', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('other_phone', salesforce.fields.CharField(blank=True, max_length=40, null=True)), - ('email', salesforce.fields.EmailField(blank=True, max_length=254, null=True)), - ('title', salesforce.fields.CharField(blank=True, max_length=128, null=True)), - ('department', salesforce.fields.CharField(blank=True, max_length=80, null=True)), - ('birthdate', salesforce.fields.DateField(blank=True, null=True)), - ('created_date', salesforce.fields.DateTimeField()), - ('last_modified_date', salesforce.fields.DateTimeField()), - ('system_modstamp', salesforce.fields.DateTimeField()), - ('last_activity_date', salesforce.fields.DateField(blank=True, null=True, verbose_name='Last Activity')), - ('last_curequest_date', salesforce.fields.DateTimeField(blank=True, db_column='LastCURequestDate', null=True, verbose_name='Last Stay-in-Touch Request Date')), - ('last_cuupdate_date', salesforce.fields.DateTimeField(blank=True, db_column='LastCUUpdateDate', null=True, verbose_name='Last Stay-in-Touch Save Date')), - ('last_viewed_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('last_referenced_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('email_bounced_reason', salesforce.fields.CharField(blank=True, max_length=255, null=True)), - ('email_bounced_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('is_email_bounced', salesforce.fields.BooleanField(default=False)), - ('photo_url', salesforce.fields.URLField(blank=True, null=True, verbose_name='Photo URL')), - ('jigsaw_contact_id', salesforce.fields.CharField(blank=True, max_length=20, null=True, verbose_name='Jigsaw Contact ID')), - ('race', salesforce.fields.CharField(blank=True, choices=[('American Indian/Alaskan Native', 'American Indian/Alaskan Native'), ('Asian', 'Asian'), ('Black/African American', 'Black/African American'), ('Native Hawaiian/Other Pacific Islander', 'Native Hawaiian/Other Pacific Islander'), ('White', 'White'), ('American Indian/Alaskan Native AND Black/African American', 'American Indian/Alaskan Native AND Black/African American'), ('American Indian/Alaskan Native AND White', 'American Indian/Alaskan Native AND White'), ('Asian AND White', 'Asian AND White'), ('Black/African American AND White', 'Black/African American AND White'), ('Other/Multiracial', 'Other/Multiracial'), ('Politely Decline', 'Politely Decline')], max_length=255, null=True, verbose_name='Which best describes your race?')), - ('gender', salesforce.fields.CharField(blank=True, choices=[('Female', 'Female'), ('Male', 'Male'), ('Genderqueer/Gender Non-binary', 'Genderqueer/Gender Non-binary'), ('Trans Female', 'Trans Female'), ('Trans Male', 'Trans Male'), ('Other', 'Not Listed')], max_length=255, null=True)), - ('which_best_describes_your_ethnicity', salesforce.fields.CharField(blank=True, choices=[('Hispanic/Latinx', 'Hispanic/Latinx'), ('Not Hispanic/Latinx', 'Not Hispanic/Latinx'), ('Politely Decline', 'Politely Decline')], db_column='Which_best_describes_your_ethnicity__c', max_length=255, null=True, verbose_name='Which best describes your ethnicity?')), - ('expected_graduation_year', salesforce.fields.CharField(blank=True, db_column='Expected_graduation_year__c', help_text='Enter the year this contact is expected to graduate. For example, 2020', max_length=4, null=True, verbose_name='Expected graduation year')), - ('current_grade_level', salesforce.fields.CharField(blank=True, db_column='Current_grade_level__c', max_length=1300, null=True, verbose_name='Current grade level')), - ('volunteer_area_s_of_interest', salesforce.fields.CharField(blank=True, choices=[('Classroom', 'Classroom'), ('Event', 'Event'), ('Other', 'Other')], db_column='Volunteer_area_s_of_interest__c', max_length=4099, null=True, verbose_name='Volunteer area(s) of interest')), - ('enrollments_this_semester_applied', salesforce.fields.DecimalField(blank=True, db_column='enrollments_this_semester_Applied__c', decimal_places=0, help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_digits=2, null=True, verbose_name='# enrollments this semester - Applied')), - ('enrollments_this_semester_waitlisted', salesforce.fields.DecimalField(blank=True, db_column='enrollments_this_semester_Waitlisted__c', decimal_places=0, help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_digits=2, null=True, verbose_name='# enrollments this semester - Waitlisted')), - ('enrollments_this_semester_rejected', salesforce.fields.DecimalField(blank=True, db_column='enrollments_this_semester_Rejected__c', decimal_places=0, help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_digits=2, null=True, verbose_name='# enrollments this semester - Rejected')), - ('enrollments_this_semester_drop_out', salesforce.fields.DecimalField(blank=True, db_column='enrollments_this_semester_Drop_out__c', decimal_places=0, help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_digits=2, null=True, verbose_name='# enrollments this semester - Drop out')), - ('race_other', salesforce.fields.CharField(blank=True, db_column='Race_Other__c', max_length=100, null=True, verbose_name='Which best describes your race? (Other)')), - ('gender_other', salesforce.fields.CharField(blank=True, db_column='Gender_Other__c', max_length=50, null=True, verbose_name='Gender (Other)')), - ('parent_guardian_first_name', salesforce.fields.CharField(blank=True, db_column='Parent_Guardian_first_name__c', max_length=100, null=True, verbose_name='Parent/Guardian first name')), - ('parent_guardian_last_name', salesforce.fields.CharField(blank=True, db_column='Parent_Guardian_last_name__c', max_length=100, null=True, verbose_name='Parent/Guardian last name')), - ('parent_guardian_phone', salesforce.fields.CharField(blank=True, db_column='Parent_Guardian_phone__c', max_length=40, null=True, verbose_name='Parent/Guardian phone')), - ('parent_guardian_email', salesforce.fields.EmailField(blank=True, db_column='Parent_Guardian_email__c', max_length=254, null=True, verbose_name='Parent/Guardian email')), - ('dm_current_grade', salesforce.fields.CharField(blank=True, choices=[('Graduating 8th', 'Graduating 8th'), ('Freshman, 9th', 'Freshman, 9th'), ('Sophomore, 10th', 'Sophomore, 10th'), ('Junior, 11th', 'Junior, 11th'), ('Senior, 12th', 'Senior, 12th')], db_column='DM_Current_grade__c', help_text='Need this for data migration to calculate Expected Graduation Year? If not, delete this field.', max_length=255, null=True, verbose_name='DM - Current grade')), - ('client_id', salesforce.fields.CharField(blank=True, db_column='Client_ID__c', help_text='3 first letters of first name, 3 first letters of last name, and birthdate "AAABBB00000000" (Only used for students and parents). This field is auto-populated by FormAssembly.', max_length=14, null=True, verbose_name='Client ID')), - ('account', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_account_set', to='home.Account')), - ('created_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_createdby_set', to='home.User')), - ('individual', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='home.Individual')), - ('last_modified_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_lastmodifiedby_set', to='home.User')), - ('master_record', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_masterrecord_set', to='home.Contact')), - ('npsp_primary_affiliation', salesforce.fields.ForeignKey(blank=True, db_column='npsp__Primary_Affiliation__c', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_npspprimaryaffiliation_set', to='home.Account')), - ('owner', salesforce.fields.ForeignKey(blank=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='contact_owner_set', to='home.User')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_deleted", + salesforce.fields.BooleanField( + default=False, verbose_name="Deleted" + ), + ), + ("last_name", salesforce.fields.CharField(max_length=80)), + ( + "first_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "salutation", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Mr.", "Mr."), + ("Ms.", "Ms."), + ("Mrs.", "Mrs."), + ("Dr.", "Dr."), + ("Prof.", "Prof."), + ], + max_length=40, + null=True, + ), + ), + ( + "middle_name", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "suffix", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "name", + salesforce.fields.CharField( + max_length=121, verbose_name="Full Name" + ), + ), + ("mailing_street", salesforce.fields.TextField(blank=True, null=True)), + ( + "mailing_city", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "mailing_state", + salesforce.fields.CharField( + blank=True, + max_length=80, + null=True, + verbose_name="Mailing State/Province", + ), + ), + ( + "mailing_postal_code", + salesforce.fields.CharField( + blank=True, + max_length=20, + null=True, + verbose_name="Mailing Zip/Postal Code", + ), + ), + ( + "mailing_country", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ( + "mailing_state_code", + salesforce.fields.CharField( + blank=True, + choices=[ + ("AC", "Acre"), + ("AG", "Agrigento"), + ("AG", "Aguascalientes"), + ("AL", "Alabama"), + ("AL", "Alagoas"), + ("AK", "Alaska"), + ("AB", "Alberta"), + ("AL", "Alessandria"), + ("AP", "Amapá"), + ("AM", "Amazonas"), + ("AN", "Ancona"), + ("AN", "Andaman and Nicobar Islands"), + ("AP", "Andhra Pradesh"), + ("34", "Anhui"), + ("AO", "Aosta"), + ("AR", "Arezzo"), + ("AZ", "Arizona"), + ("AR", "Arkansas"), + ("AR", "Arunachal Pradesh"), + ("AP", "Ascoli Piceno"), + ("AS", "Assam"), + ("AT", "Asti"), + ("ACT", "Australian Capital Territory"), + ("AV", "Avellino"), + ("BA", "Bahia"), + ("BC", "Baja California"), + ("BS", "Baja California Sur"), + ("BA", "Bari"), + ("BT", "Barletta-Andria-Trani"), + ("11", "Beijing"), + ("BL", "Belluno"), + ("BN", "Benevento"), + ("BG", "Bergamo"), + ("BI", "Biella"), + ("BR", "Bihar"), + ("BO", "Bologna"), + ("BZ", "Bolzano"), + ("BS", "Brescia"), + ("BR", "Brindisi"), + ("BC", "British Columbia"), + ("CA", "Cagliari"), + ("CA", "California"), + ("CL", "Caltanissetta"), + ("CM", "Campeche"), + ("CB", "Campobasso"), + ("CI", "Carbonia-Iglesias"), + ("CW", "Carlow"), + ("CE", "Caserta"), + ("CT", "Catania"), + ("CZ", "Catanzaro"), + ("CN", "Cavan"), + ("CE", "Ceará"), + ("CH", "Chandigarh"), + ("CT", "Chhattisgarh"), + ("CS", "Chiapas"), + ("CH", "Chieti"), + ("CH", "Chihuahua"), + ("71", "Chinese Taipei"), + ("50", "Chongqing"), + ("CE", "Clare"), + ("CO", "Coahuila"), + ("CL", "Colima"), + ("CO", "Colorado"), + ("CO", "Como"), + ("CT", "Connecticut"), + ("CO", "Cork"), + ("CS", "Cosenza"), + ("CR", "Cremona"), + ("KR", "Crotone"), + ("CN", "Cuneo"), + ("DN", "Dadra and Nagar Haveli"), + ("DD", "Daman and Diu"), + ("DE", "Delaware"), + ("DL", "Delhi"), + ("DC", "District of Columbia"), + ("DF", "Distrito Federal"), + ("DL", "Donegal"), + ("D", "Dublin"), + ("DG", "Durango"), + ("EN", "Enna"), + ("ES", "Espírito Santo"), + ("DF", "Federal District"), + ("FM", "Fermo"), + ("FE", "Ferrara"), + ("FI", "Florence"), + ("FL", "Florida"), + ("FG", "Foggia"), + ("FC", "Forlì-Cesena"), + ("FR", "Frosinone"), + ("35", "Fujian"), + ("G", "Galway"), + ("62", "Gansu"), + ("GE", "Genoa"), + ("GA", "Georgia"), + ("GA", "Goa"), + ("GO", "Goiás"), + ("GO", "Gorizia"), + ("GR", "Grosseto"), + ("GT", "Guanajuato"), + ("44", "Guangdong"), + ("45", "Guangxi"), + ("GR", "Guerrero"), + ("52", "Guizhou"), + ("GJ", "Gujarat"), + ("46", "Hainan"), + ("HR", "Haryana"), + ("HI", "Hawaii"), + ("13", "Hebei"), + ("23", "Heilongjiang"), + ("41", "Henan"), + ("HG", "Hidalgo"), + ("HP", "Himachal Pradesh"), + ("91", "Hong Kong"), + ("42", "Hubei"), + ("43", "Hunan"), + ("ID", "Idaho"), + ("IL", "Illinois"), + ("IM", "Imperia"), + ("IN", "Indiana"), + ("IA", "Iowa"), + ("IS", "Isernia"), + ("JA", "Jalisco"), + ("JK", "Jammu and Kashmir"), + ("JH", "Jharkhand"), + ("32", "Jiangsu"), + ("36", "Jiangxi"), + ("22", "Jilin"), + ("KS", "Kansas"), + ("KA", "Karnataka"), + ("KY", "Kentucky"), + ("KL", "Kerala"), + ("KY", "Kerry"), + ("KE", "Kildare"), + ("KK", "Kilkenny"), + ("AQ", "L'Aquila"), + ("LD", "Lakshadweep"), + ("LS", "Laois"), + ("SP", "La Spezia"), + ("LT", "Latina"), + ("LE", "Lecce"), + ("LC", "Lecco"), + ("LM", "Leitrim"), + ("21", "Liaoning"), + ("LK", "Limerick"), + ("LI", "Livorno"), + ("LO", "Lodi"), + ("LD", "Longford"), + ("LA", "Louisiana"), + ("LH", "Louth"), + ("LU", "Lucca"), + ("92", "Macao"), + ("MC", "Macerata"), + ("MP", "Madhya Pradesh"), + ("MH", "Maharashtra"), + ("ME", "Maine"), + ("MN", "Manipur"), + ("MB", "Manitoba"), + ("MN", "Mantua"), + ("MA", "Maranhão"), + ("MD", "Maryland"), + ("MS", "Massa and Carrara"), + ("MA", "Massachusetts"), + ("MT", "Matera"), + ("MT", "Mato Grosso"), + ("MS", "Mato Grosso do Sul"), + ("MO", "Mayo"), + ("MH", "Meath"), + ("VS", "Medio Campidano"), + ("ML", "Meghalaya"), + ("ME", "Messina"), + ("ME", "Mexico State"), + ("MI", "Michigan"), + ("MI", "Michoacán"), + ("MI", "Milan"), + ("MG", "Minas Gerais"), + ("MN", "Minnesota"), + ("MS", "Mississippi"), + ("MO", "Missouri"), + ("MZ", "Mizoram"), + ("MO", "Modena"), + ("MN", "Monaghan"), + ("MT", "Montana"), + ("MB", "Monza and Brianza"), + ("MO", "Morelos"), + ("NL", "Nagaland"), + ("NA", "Naples"), + ("NA", "Nayarit"), + ("NE", "Nebraska"), + ("15", "Nei Mongol"), + ("NV", "Nevada"), + ("NB", "New Brunswick"), + ("NL", "Newfoundland and Labrador"), + ("NH", "New Hampshire"), + ("NJ", "New Jersey"), + ("NM", "New Mexico"), + ("NSW", "New South Wales"), + ("NY", "New York"), + ("64", "Ningxia"), + ("NC", "North Carolina"), + ("ND", "North Dakota"), + ("NT", "Northern Territory"), + ("NT", "Northwest Territories"), + ("NO", "Novara"), + ("NS", "Nova Scotia"), + ("NL", "Nuevo León"), + ("NU", "Nunavut"), + ("NU", "Nuoro"), + ("OA", "Oaxaca"), + ("OR", "Odisha"), + ("OY", "Offaly"), + ("OG", "Ogliastra"), + ("OH", "Ohio"), + ("OK", "Oklahoma"), + ("OT", "Olbia-Tempio"), + ("ON", "Ontario"), + ("OR", "Oregon"), + ("OR", "Oristano"), + ("PD", "Padua"), + ("PA", "Palermo"), + ("PA", "Pará"), + ("PB", "Paraíba"), + ("PR", "Paraná"), + ("PR", "Parma"), + ("PV", "Pavia"), + ("PA", "Pennsylvania"), + ("PE", "Pernambuco"), + ("PG", "Perugia"), + ("PU", "Pesaro and Urbino"), + ("PE", "Pescara"), + ("PC", "Piacenza"), + ("PI", "Piauí"), + ("PI", "Pisa"), + ("PT", "Pistoia"), + ("PN", "Pordenone"), + ("PZ", "Potenza"), + ("PO", "Prato"), + ("PE", "Prince Edward Island"), + ("PY", "Puducherry"), + ("PB", "Puebla"), + ("PB", "Punjab"), + ("63", "Qinghai"), + ("QC", "Quebec"), + ("QLD", "Queensland"), + ("QE", "Querétaro"), + ("QR", "Quintana Roo"), + ("RG", "Ragusa"), + ("RJ", "Rajasthan"), + ("RA", "Ravenna"), + ("RC", "Reggio Calabria"), + ("RE", "Reggio Emilia"), + ("RI", "Rhode Island"), + ("RI", "Rieti"), + ("RN", "Rimini"), + ("RJ", "Rio de Janeiro"), + ("RN", "Rio Grande do Norte"), + ("RS", "Rio Grande do Sul"), + ("RM", "Rome"), + ("RO", "Rondônia"), + ("RR", "Roraima"), + ("RN", "Roscommon"), + ("RO", "Rovigo"), + ("SA", "Salerno"), + ("SL", "San Luis Potosí"), + ("SC", "Santa Catarina"), + ("SP", "São Paulo"), + ("SK", "Saskatchewan"), + ("SS", "Sassari"), + ("SV", "Savona"), + ("SE", "Sergipe"), + ("61", "Shaanxi"), + ("37", "Shandong"), + ("31", "Shanghai"), + ("14", "Shanxi"), + ("51", "Sichuan"), + ("SI", "Siena"), + ("SK", "Sikkim"), + ("SI", "Sinaloa"), + ("SO", "Sligo"), + ("SO", "Sondrio"), + ("SO", "Sonora"), + ("SA", "South Australia"), + ("SC", "South Carolina"), + ("SD", "South Dakota"), + ("SR", "Syracuse"), + ("TB", "Tabasco"), + ("TM", "Tamaulipas"), + ("TN", "Tamil Nadu"), + ("TA", "Taranto"), + ("TAS", "Tasmania"), + ("TN", "Tennessee"), + ("TE", "Teramo"), + ("TR", "Terni"), + ("TX", "Texas"), + ("12", "Tianjin"), + ("TA", "Tipperary"), + ("TL", "Tlaxcala"), + ("TO", "Tocantins"), + ("TP", "Trapani"), + ("TN", "Trento"), + ("TV", "Treviso"), + ("TS", "Trieste"), + ("TR", "Tripura"), + ("TO", "Turin"), + ("UD", "Udine"), + ("UT", "Utah"), + ("UT", "Uttarakhand"), + ("UP", "Uttar Pradesh"), + ("VA", "Varese"), + ("VE", "Venice"), + ("VE", "Veracruz"), + ("VB", "Verbano-Cusio-Ossola"), + ("VC", "Vercelli"), + ("VT", "Vermont"), + ("VR", "Verona"), + ("VV", "Vibo Valentia"), + ("VI", "Vicenza"), + ("VIC", "Victoria"), + ("VA", "Virginia"), + ("VT", "Viterbo"), + ("WA", "Washington"), + ("WD", "Waterford"), + ("WB", "West Bengal"), + ("WA", "Western Australia"), + ("WH", "Westmeath"), + ("WV", "West Virginia"), + ("WX", "Wexford"), + ("WW", "Wicklow"), + ("WI", "Wisconsin"), + ("WY", "Wyoming"), + ("65", "Xinjiang"), + ("54", "Xizang"), + ("YU", "Yucatán"), + ("YT", "Yukon Territories"), + ("53", "Yunnan"), + ("ZA", "Zacatecas"), + ("33", "Zhejiang"), + ], + max_length=10, + null=True, + verbose_name="Mailing State/Province Code", + ), + ), + ( + "mailing_country_code", + salesforce.fields.CharField( + blank=True, + choices=[ + ("AC", "Acre"), + ("AG", "Agrigento"), + ("AG", "Aguascalientes"), + ("AL", "Alabama"), + ("AL", "Alagoas"), + ("AK", "Alaska"), + ("AB", "Alberta"), + ("AL", "Alessandria"), + ("AP", "Amapá"), + ("AM", "Amazonas"), + ("AN", "Ancona"), + ("AN", "Andaman and Nicobar Islands"), + ("AP", "Andhra Pradesh"), + ("34", "Anhui"), + ("AO", "Aosta"), + ("AR", "Arezzo"), + ("AZ", "Arizona"), + ("AR", "Arkansas"), + ("AR", "Arunachal Pradesh"), + ("AP", "Ascoli Piceno"), + ("AS", "Assam"), + ("AT", "Asti"), + ("ACT", "Australian Capital Territory"), + ("AV", "Avellino"), + ("BA", "Bahia"), + ("BC", "Baja California"), + ("BS", "Baja California Sur"), + ("BA", "Bari"), + ("BT", "Barletta-Andria-Trani"), + ("11", "Beijing"), + ("BL", "Belluno"), + ("BN", "Benevento"), + ("BG", "Bergamo"), + ("BI", "Biella"), + ("BR", "Bihar"), + ("BO", "Bologna"), + ("BZ", "Bolzano"), + ("BS", "Brescia"), + ("BR", "Brindisi"), + ("BC", "British Columbia"), + ("CA", "Cagliari"), + ("CA", "California"), + ("CL", "Caltanissetta"), + ("CM", "Campeche"), + ("CB", "Campobasso"), + ("CI", "Carbonia-Iglesias"), + ("CW", "Carlow"), + ("CE", "Caserta"), + ("CT", "Catania"), + ("CZ", "Catanzaro"), + ("CN", "Cavan"), + ("CE", "Ceará"), + ("CH", "Chandigarh"), + ("CT", "Chhattisgarh"), + ("CS", "Chiapas"), + ("CH", "Chieti"), + ("CH", "Chihuahua"), + ("71", "Chinese Taipei"), + ("50", "Chongqing"), + ("CE", "Clare"), + ("CO", "Coahuila"), + ("CL", "Colima"), + ("CO", "Colorado"), + ("CO", "Como"), + ("CT", "Connecticut"), + ("CO", "Cork"), + ("CS", "Cosenza"), + ("CR", "Cremona"), + ("KR", "Crotone"), + ("CN", "Cuneo"), + ("DN", "Dadra and Nagar Haveli"), + ("DD", "Daman and Diu"), + ("DE", "Delaware"), + ("DL", "Delhi"), + ("DC", "District of Columbia"), + ("DF", "Distrito Federal"), + ("DL", "Donegal"), + ("D", "Dublin"), + ("DG", "Durango"), + ("EN", "Enna"), + ("ES", "Espírito Santo"), + ("DF", "Federal District"), + ("FM", "Fermo"), + ("FE", "Ferrara"), + ("FI", "Florence"), + ("FL", "Florida"), + ("FG", "Foggia"), + ("FC", "Forlì-Cesena"), + ("FR", "Frosinone"), + ("35", "Fujian"), + ("G", "Galway"), + ("62", "Gansu"), + ("GE", "Genoa"), + ("GA", "Georgia"), + ("GA", "Goa"), + ("GO", "Goiás"), + ("GO", "Gorizia"), + ("GR", "Grosseto"), + ("GT", "Guanajuato"), + ("44", "Guangdong"), + ("45", "Guangxi"), + ("GR", "Guerrero"), + ("52", "Guizhou"), + ("GJ", "Gujarat"), + ("46", "Hainan"), + ("HR", "Haryana"), + ("HI", "Hawaii"), + ("13", "Hebei"), + ("23", "Heilongjiang"), + ("41", "Henan"), + ("HG", "Hidalgo"), + ("HP", "Himachal Pradesh"), + ("91", "Hong Kong"), + ("42", "Hubei"), + ("43", "Hunan"), + ("ID", "Idaho"), + ("IL", "Illinois"), + ("IM", "Imperia"), + ("IN", "Indiana"), + ("IA", "Iowa"), + ("IS", "Isernia"), + ("JA", "Jalisco"), + ("JK", "Jammu and Kashmir"), + ("JH", "Jharkhand"), + ("32", "Jiangsu"), + ("36", "Jiangxi"), + ("22", "Jilin"), + ("KS", "Kansas"), + ("KA", "Karnataka"), + ("KY", "Kentucky"), + ("KL", "Kerala"), + ("KY", "Kerry"), + ("KE", "Kildare"), + ("KK", "Kilkenny"), + ("AQ", "L'Aquila"), + ("LD", "Lakshadweep"), + ("LS", "Laois"), + ("SP", "La Spezia"), + ("LT", "Latina"), + ("LE", "Lecce"), + ("LC", "Lecco"), + ("LM", "Leitrim"), + ("21", "Liaoning"), + ("LK", "Limerick"), + ("LI", "Livorno"), + ("LO", "Lodi"), + ("LD", "Longford"), + ("LA", "Louisiana"), + ("LH", "Louth"), + ("LU", "Lucca"), + ("92", "Macao"), + ("MC", "Macerata"), + ("MP", "Madhya Pradesh"), + ("MH", "Maharashtra"), + ("ME", "Maine"), + ("MN", "Manipur"), + ("MB", "Manitoba"), + ("MN", "Mantua"), + ("MA", "Maranhão"), + ("MD", "Maryland"), + ("MS", "Massa and Carrara"), + ("MA", "Massachusetts"), + ("MT", "Matera"), + ("MT", "Mato Grosso"), + ("MS", "Mato Grosso do Sul"), + ("MO", "Mayo"), + ("MH", "Meath"), + ("VS", "Medio Campidano"), + ("ML", "Meghalaya"), + ("ME", "Messina"), + ("ME", "Mexico State"), + ("MI", "Michigan"), + ("MI", "Michoacán"), + ("MI", "Milan"), + ("MG", "Minas Gerais"), + ("MN", "Minnesota"), + ("MS", "Mississippi"), + ("MO", "Missouri"), + ("MZ", "Mizoram"), + ("MO", "Modena"), + ("MN", "Monaghan"), + ("MT", "Montana"), + ("MB", "Monza and Brianza"), + ("MO", "Morelos"), + ("NL", "Nagaland"), + ("NA", "Naples"), + ("NA", "Nayarit"), + ("NE", "Nebraska"), + ("15", "Nei Mongol"), + ("NV", "Nevada"), + ("NB", "New Brunswick"), + ("NL", "Newfoundland and Labrador"), + ("NH", "New Hampshire"), + ("NJ", "New Jersey"), + ("NM", "New Mexico"), + ("NSW", "New South Wales"), + ("NY", "New York"), + ("64", "Ningxia"), + ("NC", "North Carolina"), + ("ND", "North Dakota"), + ("NT", "Northern Territory"), + ("NT", "Northwest Territories"), + ("NO", "Novara"), + ("NS", "Nova Scotia"), + ("NL", "Nuevo León"), + ("NU", "Nunavut"), + ("NU", "Nuoro"), + ("OA", "Oaxaca"), + ("OR", "Odisha"), + ("OY", "Offaly"), + ("OG", "Ogliastra"), + ("OH", "Ohio"), + ("OK", "Oklahoma"), + ("OT", "Olbia-Tempio"), + ("ON", "Ontario"), + ("OR", "Oregon"), + ("OR", "Oristano"), + ("PD", "Padua"), + ("PA", "Palermo"), + ("PA", "Pará"), + ("PB", "Paraíba"), + ("PR", "Paraná"), + ("PR", "Parma"), + ("PV", "Pavia"), + ("PA", "Pennsylvania"), + ("PE", "Pernambuco"), + ("PG", "Perugia"), + ("PU", "Pesaro and Urbino"), + ("PE", "Pescara"), + ("PC", "Piacenza"), + ("PI", "Piauí"), + ("PI", "Pisa"), + ("PT", "Pistoia"), + ("PN", "Pordenone"), + ("PZ", "Potenza"), + ("PO", "Prato"), + ("PE", "Prince Edward Island"), + ("PY", "Puducherry"), + ("PB", "Puebla"), + ("PB", "Punjab"), + ("63", "Qinghai"), + ("QC", "Quebec"), + ("QLD", "Queensland"), + ("QE", "Querétaro"), + ("QR", "Quintana Roo"), + ("RG", "Ragusa"), + ("RJ", "Rajasthan"), + ("RA", "Ravenna"), + ("RC", "Reggio Calabria"), + ("RE", "Reggio Emilia"), + ("RI", "Rhode Island"), + ("RI", "Rieti"), + ("RN", "Rimini"), + ("RJ", "Rio de Janeiro"), + ("RN", "Rio Grande do Norte"), + ("RS", "Rio Grande do Sul"), + ("RM", "Rome"), + ("RO", "Rondônia"), + ("RR", "Roraima"), + ("RN", "Roscommon"), + ("RO", "Rovigo"), + ("SA", "Salerno"), + ("SL", "San Luis Potosí"), + ("SC", "Santa Catarina"), + ("SP", "São Paulo"), + ("SK", "Saskatchewan"), + ("SS", "Sassari"), + ("SV", "Savona"), + ("SE", "Sergipe"), + ("61", "Shaanxi"), + ("37", "Shandong"), + ("31", "Shanghai"), + ("14", "Shanxi"), + ("51", "Sichuan"), + ("SI", "Siena"), + ("SK", "Sikkim"), + ("SI", "Sinaloa"), + ("SO", "Sligo"), + ("SO", "Sondrio"), + ("SO", "Sonora"), + ("SA", "South Australia"), + ("SC", "South Carolina"), + ("SD", "South Dakota"), + ("SR", "Syracuse"), + ("TB", "Tabasco"), + ("TM", "Tamaulipas"), + ("TN", "Tamil Nadu"), + ("TA", "Taranto"), + ("TAS", "Tasmania"), + ("TN", "Tennessee"), + ("TE", "Teramo"), + ("TR", "Terni"), + ("TX", "Texas"), + ("12", "Tianjin"), + ("TA", "Tipperary"), + ("TL", "Tlaxcala"), + ("TO", "Tocantins"), + ("TP", "Trapani"), + ("TN", "Trento"), + ("TV", "Treviso"), + ("TS", "Trieste"), + ("TR", "Tripura"), + ("TO", "Turin"), + ("UD", "Udine"), + ("UT", "Utah"), + ("UT", "Uttarakhand"), + ("UP", "Uttar Pradesh"), + ("VA", "Varese"), + ("VE", "Venice"), + ("VE", "Veracruz"), + ("VB", "Verbano-Cusio-Ossola"), + ("VC", "Vercelli"), + ("VT", "Vermont"), + ("VR", "Verona"), + ("VV", "Vibo Valentia"), + ("VI", "Vicenza"), + ("VIC", "Victoria"), + ("VA", "Virginia"), + ("VT", "Viterbo"), + ("WA", "Washington"), + ("WD", "Waterford"), + ("WB", "West Bengal"), + ("WA", "Western Australia"), + ("WH", "Westmeath"), + ("WV", "West Virginia"), + ("WX", "Wexford"), + ("WW", "Wicklow"), + ("WI", "Wisconsin"), + ("WY", "Wyoming"), + ("65", "Xinjiang"), + ("54", "Xizang"), + ("YU", "Yucatán"), + ("YT", "Yukon Territories"), + ("53", "Yunnan"), + ("ZA", "Zacatecas"), + ("33", "Zhejiang"), + ], + default=salesforce.backend.operations.DefaultedOnCreate(), + max_length=10, + null=True, + ), + ), + ( + "mobile_phone", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "home_phone", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "other_phone", + salesforce.fields.CharField(blank=True, max_length=40, null=True), + ), + ( + "email", + salesforce.fields.EmailField(blank=True, max_length=254, null=True), + ), + ( + "title", + salesforce.fields.CharField(blank=True, max_length=128, null=True), + ), + ( + "department", + salesforce.fields.CharField(blank=True, max_length=80, null=True), + ), + ("birthdate", salesforce.fields.DateField(blank=True, null=True)), + ("created_date", salesforce.fields.DateTimeField()), + ("last_modified_date", salesforce.fields.DateTimeField()), + ("system_modstamp", salesforce.fields.DateTimeField()), + ( + "last_activity_date", + salesforce.fields.DateField( + blank=True, null=True, verbose_name="Last Activity" + ), + ), + ( + "last_curequest_date", + salesforce.fields.DateTimeField( + blank=True, + db_column="LastCURequestDate", + null=True, + verbose_name="Last Stay-in-Touch Request Date", + ), + ), + ( + "last_cuupdate_date", + salesforce.fields.DateTimeField( + blank=True, + db_column="LastCUUpdateDate", + null=True, + verbose_name="Last Stay-in-Touch Save Date", + ), + ), + ( + "last_viewed_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "last_referenced_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "email_bounced_reason", + salesforce.fields.CharField(blank=True, max_length=255, null=True), + ), + ( + "email_bounced_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ("is_email_bounced", salesforce.fields.BooleanField(default=False)), + ( + "photo_url", + salesforce.fields.URLField( + blank=True, null=True, verbose_name="Photo URL" + ), + ), + ( + "jigsaw_contact_id", + salesforce.fields.CharField( + blank=True, + max_length=20, + null=True, + verbose_name="Jigsaw Contact ID", + ), + ), + ( + "race", + salesforce.fields.CharField( + blank=True, + choices=[ + ( + "American Indian/Alaskan Native", + "American Indian/Alaskan Native", + ), + ("Asian", "Asian"), + ("Black/African American", "Black/African American"), + ( + "Native Hawaiian/Other Pacific Islander", + "Native Hawaiian/Other Pacific Islander", + ), + ("White", "White"), + ( + "American Indian/Alaskan Native AND Black/African American", + "American Indian/Alaskan Native AND Black/African American", + ), + ( + "American Indian/Alaskan Native AND White", + "American Indian/Alaskan Native AND White", + ), + ("Asian AND White", "Asian AND White"), + ( + "Black/African American AND White", + "Black/African American AND White", + ), + ("Other/Multiracial", "Other/Multiracial"), + ("Politely Decline", "Politely Decline"), + ], + max_length=255, + null=True, + verbose_name="Which best describes your race?", + ), + ), + ( + "gender", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Female", "Female"), + ("Male", "Male"), + ( + "Genderqueer/Gender Non-binary", + "Genderqueer/Gender Non-binary", + ), + ("Trans Female", "Trans Female"), + ("Trans Male", "Trans Male"), + ("Other", "Not Listed"), + ], + max_length=255, + null=True, + ), + ), + ( + "which_best_describes_your_ethnicity", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Hispanic/Latinx", "Hispanic/Latinx"), + ("Not Hispanic/Latinx", "Not Hispanic/Latinx"), + ("Politely Decline", "Politely Decline"), + ], + db_column="Which_best_describes_your_ethnicity__c", + max_length=255, + null=True, + verbose_name="Which best describes your ethnicity?", + ), + ), + ( + "expected_graduation_year", + salesforce.fields.CharField( + blank=True, + db_column="Expected_graduation_year__c", + help_text="Enter the year this contact is expected to graduate. For example, 2020", + max_length=4, + null=True, + verbose_name="Expected graduation year", + ), + ), + ( + "current_grade_level", + salesforce.fields.CharField( + blank=True, + db_column="Current_grade_level__c", + max_length=1300, + null=True, + verbose_name="Current grade level", + ), + ), + ( + "volunteer_area_s_of_interest", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Classroom", "Classroom"), + ("Event", "Event"), + ("Other", "Other"), + ], + db_column="Volunteer_area_s_of_interest__c", + max_length=4099, + null=True, + verbose_name="Volunteer area(s) of interest", + ), + ), + ( + "enrollments_this_semester_applied", + salesforce.fields.DecimalField( + blank=True, + db_column="enrollments_this_semester_Applied__c", + decimal_places=0, + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_digits=2, + null=True, + verbose_name="# enrollments this semester - Applied", + ), + ), + ( + "enrollments_this_semester_waitlisted", + salesforce.fields.DecimalField( + blank=True, + db_column="enrollments_this_semester_Waitlisted__c", + decimal_places=0, + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_digits=2, + null=True, + verbose_name="# enrollments this semester - Waitlisted", + ), + ), + ( + "enrollments_this_semester_rejected", + salesforce.fields.DecimalField( + blank=True, + db_column="enrollments_this_semester_Rejected__c", + decimal_places=0, + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_digits=2, + null=True, + verbose_name="# enrollments this semester - Rejected", + ), + ), + ( + "enrollments_this_semester_drop_out", + salesforce.fields.DecimalField( + blank=True, + db_column="enrollments_this_semester_Drop_out__c", + decimal_places=0, + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_digits=2, + null=True, + verbose_name="# enrollments this semester - Drop out", + ), + ), + ( + "race_other", + salesforce.fields.CharField( + blank=True, + db_column="Race_Other__c", + max_length=100, + null=True, + verbose_name="Which best describes your race? (Other)", + ), + ), + ( + "gender_other", + salesforce.fields.CharField( + blank=True, + db_column="Gender_Other__c", + max_length=50, + null=True, + verbose_name="Gender (Other)", + ), + ), + ( + "parent_guardian_first_name", + salesforce.fields.CharField( + blank=True, + db_column="Parent_Guardian_first_name__c", + max_length=100, + null=True, + verbose_name="Parent/Guardian first name", + ), + ), + ( + "parent_guardian_last_name", + salesforce.fields.CharField( + blank=True, + db_column="Parent_Guardian_last_name__c", + max_length=100, + null=True, + verbose_name="Parent/Guardian last name", + ), + ), + ( + "parent_guardian_phone", + salesforce.fields.CharField( + blank=True, + db_column="Parent_Guardian_phone__c", + max_length=40, + null=True, + verbose_name="Parent/Guardian phone", + ), + ), + ( + "parent_guardian_email", + salesforce.fields.EmailField( + blank=True, + db_column="Parent_Guardian_email__c", + max_length=254, + null=True, + verbose_name="Parent/Guardian email", + ), + ), + ( + "dm_current_grade", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Graduating 8th", "Graduating 8th"), + ("Freshman, 9th", "Freshman, 9th"), + ("Sophomore, 10th", "Sophomore, 10th"), + ("Junior, 11th", "Junior, 11th"), + ("Senior, 12th", "Senior, 12th"), + ], + db_column="DM_Current_grade__c", + help_text="Need this for data migration to calculate Expected Graduation Year? If not, delete this field.", + max_length=255, + null=True, + verbose_name="DM - Current grade", + ), + ), + ( + "client_id", + salesforce.fields.CharField( + blank=True, + db_column="Client_ID__c", + help_text='3 first letters of first name, 3 first letters of last name, and birthdate "AAABBB00000000" (Only used for students and parents). This field is auto-populated by FormAssembly.', + max_length=14, + null=True, + verbose_name="Client ID", + ), + ), + ( + "account", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_account_set", + to="home.Account", + ), + ), + ( + "created_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_createdby_set", + to="home.User", + ), + ), + ( + "individual", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + to="home.Individual", + ), + ), + ( + "last_modified_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_lastmodifiedby_set", + to="home.User", + ), + ), + ( + "master_record", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_masterrecord_set", + to="home.Contact", + ), + ), + ( + "npsp_primary_affiliation", + salesforce.fields.ForeignKey( + blank=True, + db_column="npsp__Primary_Affiliation__c", + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_npspprimaryaffiliation_set", + to="home.Account", + ), + ), + ( + "owner", + salesforce.fields.ForeignKey( + blank=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="contact_owner_set", + to="home.User", + ), + ), ], options={ - 'verbose_name': 'Contact', - 'verbose_name_plural': 'Contacts', - 'db_table': 'Contact', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "Contact", + "verbose_name_plural": "Contacts", + "db_table": "Contact", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.CreateModel( - name='ClassOffering', + name="ClassOffering", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('is_deleted', salesforce.fields.BooleanField(default=False, verbose_name='Deleted')), - ('name', salesforce.fields.CharField(blank=True, default=salesforce.backend.operations.DefaultedOnCreate(), max_length=80, null=True, verbose_name='Class Offering Name')), - ('created_date', salesforce.fields.DateTimeField()), - ('last_modified_date', salesforce.fields.DateTimeField()), - ('system_modstamp', salesforce.fields.DateTimeField()), - ('last_viewed_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('last_referenced_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('start_date', salesforce.fields.DateField(blank=True, db_column='Start_Date__c', null=True, verbose_name='Start Date')), - ('end_date', salesforce.fields.DateField(blank=True, db_column='End_Date__c', null=True, verbose_name='End Date')), - ('description', salesforce.fields.TextField(blank=True, null=True)), - ('course', salesforce.fields.CharField(blank=True, choices=[('Android Game Design', 'Android Game Design'), ('Intro to Web Programming', 'Intro to Web Programming'), ('Field Trips', 'Field Trips'), ('Intro to Game Design with Unity', 'Intro to Game Design with Unity'), ('Web Design 101', 'Web Design 101'), ('Mobile App Dev with Ionic', 'Mobile App Dev with Ionic'), ('MB Internship', 'MB Internship'), ('Structured Study Program', 'Structured Study Program')], max_length=255, null=True)), - ('academic_semester', salesforce.fields.CharField(blank=True, db_column='Academic_semester__c', max_length=1300, null=True, verbose_name='Academic semester')), - ('meeting_days', salesforce.fields.CharField(blank=True, choices=[('M/W', 'M/W'), ('T/R', 'T/R'), ('M-F', 'M-F')], db_column='Meeting_Days__c', max_length=255, null=True, verbose_name='Meeting Days')), - ('count_total_female_students', salesforce.fields.DecimalField(blank=True, db_column='Count_total_female_students__c', decimal_places=0, max_digits=18, null=True, verbose_name='Count - Total Female Students')), - ('count_total_latino_african_american', salesforce.fields.DecimalField(blank=True, db_column='Count_total_latino_african_american__c', decimal_places=0, max_digits=18, null=True, verbose_name='Count - Total African American')), - ('count_total_latino_students', salesforce.fields.DecimalField(blank=True, db_column='Count_Total_Latino_Students__c', decimal_places=0, max_digits=18, null=True, verbose_name='Count - Total Latino Students')), - ('female', salesforce.fields.DecimalField(blank=True, decimal_places=1, max_digits=18, null=True, verbose_name='% Female')), - ('latino_african_american', salesforce.fields.DecimalField(blank=True, db_column='Latino_African_American__c', decimal_places=1, max_digits=18, null=True, verbose_name='% Latino/African American')), - ('current_academic_semester', salesforce.fields.CharField(blank=True, db_column='Current_academic_semester__c', max_length=1300, null=True, verbose_name='Current academic semester')), - ('in_current_semester', salesforce.fields.BooleanField(db_column='In_current_semester__c', default=False, verbose_name='In current semester?')), - ('created_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='classoffering_createdby_set', to='home.User')), - ('instructor', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='home.Contact')), - ('last_modified_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='classoffering_lastmodifiedby_set', to='home.User')), - ('location', salesforce.fields.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.DO_NOTHING, to='home.Account')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_deleted", + salesforce.fields.BooleanField( + default=False, verbose_name="Deleted" + ), + ), + ( + "name", + salesforce.fields.CharField( + blank=True, + default=salesforce.backend.operations.DefaultedOnCreate(), + max_length=80, + null=True, + verbose_name="Class Offering Name", + ), + ), + ("created_date", salesforce.fields.DateTimeField()), + ("last_modified_date", salesforce.fields.DateTimeField()), + ("system_modstamp", salesforce.fields.DateTimeField()), + ( + "last_viewed_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "last_referenced_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "start_date", + salesforce.fields.DateField( + blank=True, + db_column="Start_Date__c", + null=True, + verbose_name="Start Date", + ), + ), + ( + "end_date", + salesforce.fields.DateField( + blank=True, + db_column="End_Date__c", + null=True, + verbose_name="End Date", + ), + ), + ("description", salesforce.fields.TextField(blank=True, null=True)), + ( + "course", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Android Game Design", "Android Game Design"), + ("Intro to Web Programming", "Intro to Web Programming"), + ("Field Trips", "Field Trips"), + ( + "Intro to Game Design with Unity", + "Intro to Game Design with Unity", + ), + ("Web Design 101", "Web Design 101"), + ("Mobile App Dev with Ionic", "Mobile App Dev with Ionic"), + ("MB Internship", "MB Internship"), + ("Structured Study Program", "Structured Study Program"), + ], + max_length=255, + null=True, + ), + ), + ( + "academic_semester", + salesforce.fields.CharField( + blank=True, + db_column="Academic_semester__c", + max_length=1300, + null=True, + verbose_name="Academic semester", + ), + ), + ( + "meeting_days", + salesforce.fields.CharField( + blank=True, + choices=[("M/W", "M/W"), ("T/R", "T/R"), ("M-F", "M-F")], + db_column="Meeting_Days__c", + max_length=255, + null=True, + verbose_name="Meeting Days", + ), + ), + ( + "count_total_female_students", + salesforce.fields.DecimalField( + blank=True, + db_column="Count_total_female_students__c", + decimal_places=0, + max_digits=18, + null=True, + verbose_name="Count - Total Female Students", + ), + ), + ( + "count_total_latino_african_american", + salesforce.fields.DecimalField( + blank=True, + db_column="Count_total_latino_african_american__c", + decimal_places=0, + max_digits=18, + null=True, + verbose_name="Count - Total African American", + ), + ), + ( + "count_total_latino_students", + salesforce.fields.DecimalField( + blank=True, + db_column="Count_Total_Latino_Students__c", + decimal_places=0, + max_digits=18, + null=True, + verbose_name="Count - Total Latino Students", + ), + ), + ( + "female", + salesforce.fields.DecimalField( + blank=True, + decimal_places=1, + max_digits=18, + null=True, + verbose_name="% Female", + ), + ), + ( + "latino_african_american", + salesforce.fields.DecimalField( + blank=True, + db_column="Latino_African_American__c", + decimal_places=1, + max_digits=18, + null=True, + verbose_name="% Latino/African American", + ), + ), + ( + "current_academic_semester", + salesforce.fields.CharField( + blank=True, + db_column="Current_academic_semester__c", + max_length=1300, + null=True, + verbose_name="Current academic semester", + ), + ), + ( + "in_current_semester", + salesforce.fields.BooleanField( + db_column="In_current_semester__c", + default=False, + verbose_name="In current semester?", + ), + ), + ( + "created_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classoffering_createdby_set", + to="home.User", + ), + ), + ( + "instructor", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + to="home.Contact", + ), + ), + ( + "last_modified_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classoffering_lastmodifiedby_set", + to="home.User", + ), + ), + ( + "location", + salesforce.fields.ForeignKey( + blank=True, + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + to="home.Account", + ), + ), ], options={ - 'verbose_name': 'Class Offering', - 'verbose_name_plural': 'Class Offerings', - 'db_table': 'Class_Offering__c', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "Class Offering", + "verbose_name_plural": "Class Offerings", + "db_table": "Class_Offering__c", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.CreateModel( - name='ClassEnrollment', + name="ClassEnrollment", fields=[ - ('id', salesforce.fields.SalesforceAutoField(auto_created=True, db_column='Id', primary_key=True, serialize=False, verbose_name='ID')), - ('is_deleted', salesforce.fields.BooleanField(default=False, verbose_name='Deleted')), - ('name', salesforce.fields.CharField(max_length=80, verbose_name='Class Enrollment #')), - ('created_date', salesforce.fields.DateTimeField()), - ('last_modified_date', salesforce.fields.DateTimeField()), - ('system_modstamp', salesforce.fields.DateTimeField()), - ('last_activity_date', salesforce.fields.DateField(blank=True, null=True)), - ('last_viewed_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('last_referenced_date', salesforce.fields.DateTimeField(blank=True, null=True)), - ('role', salesforce.fields.CharField(blank=True, choices=[('Student', 'Student'), ('TA', 'TA'), ('Volunteer', 'Volunteer')], max_length=255, null=True)), - ('status', salesforce.fields.CharField(blank=True, choices=[('Applied', 'Applied'), ('Waitlisted', 'Waitlisted'), ('Enrolled', 'Enrolled'), ('Completed-Course', 'Completed-Course'), ('Withdrew-Application', 'Withdrew-Application'), ('Rejected', 'Rejected'), ('Dropped', 'Dropped')], max_length=255, null=True)), - ('in_current_semester', salesforce.fields.BooleanField(db_column='In_current_semester__c', default=False, verbose_name='In current semester?')), - ('attended_family_orientation', salesforce.fields.BooleanField(db_column='Attended_Family_Orientation__c', default=salesforce.backend.operations.DefaultedOnCreate(), verbose_name='Attended Family Orientation')), - ('withdrew_application_detail', salesforce.fields.CharField(blank=True, choices=[("Didn't show up for interview", "Didn't show up for interview"), ('Acceptance-offer-rejected', 'Acceptance-offer-rejected'), ('Didn’t show up for class', 'Didn’t show up for class'), ('Dropped in first 2 weeks', 'Dropped in first 2 weeks'), ('Withdrew before interview', 'Withdrew before interview'), ('Class Cancelled', 'Class Cancelled')], db_column='Withdrew_Application_Detail__c', help_text='"Dropped in first 2 weeks" means that they showed up for class but decided to drop within the first 2 weeks.', max_length=255, null=True, verbose_name='Withdrew-Application Detail')), - ('contact_race', salesforce.fields.CharField(blank=True, db_column='Contact_Race__c', help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_length=100, null=True, verbose_name='Contact - Race')), - ('contact_gender', salesforce.fields.CharField(blank=True, db_column='Contact_Gender__c', help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_length=30, null=True, verbose_name='Contact - Gender')), - ('attended_interview', salesforce.fields.BooleanField(db_column='Attended_Interview__c', default=salesforce.backend.operations.DefaultedOnCreate(), help_text='Check if the student attended the default student admissions interview event. Note: Do not check this field if the student attended a makeup interview.', verbose_name='Attended Interview')), - ('attended_makeup_interview', salesforce.fields.BooleanField(db_column='Attended_Makeup_Interview__c', default=salesforce.backend.operations.DefaultedOnCreate(), help_text='Check if the student did not attend the default interview date, but attended a makeup session.', verbose_name='Attended Makeup Interview')), - ('cultural_affiliation_or_nationality', salesforce.fields.CharField(blank=True, db_column='Cultural_Affiliation_or_Nationality__c', help_text='(optional)', max_length=100, null=True, verbose_name='Cultural Affiliation or Nationality')), - ('sex_at_birth', salesforce.fields.CharField(blank=True, choices=[('Female', 'Female'), ('Male', 'Male'), ('Decline to answer', 'Decline to answer')], db_column='Sex_at_birth__c', help_text='(Check one)', max_length=255, null=True, verbose_name='What was your sex at birth?')), - ('sexual_orientation', salesforce.fields.CharField(blank=True, choices=[('Bisexual', 'Bisexual'), ('Gay / Lesbian / Same-Gender Loving', 'Gay / Lesbian / Same-Gender Loving'), ('Questioning / Unsure', 'Questioning / Unsure'), ('Straight / Heterosexual', 'Straight / Heterosexual'), ('Not Listed.', 'Not Listed.'), ('Decline to answer', 'Decline to answer')], db_column='Sexual_orientation__c', help_text='How do you describe your sexual orientation or sexual identity?', max_length=255, null=True, verbose_name='Sexual orientation or sexual identity')), - ('other_sexual_orientation', salesforce.fields.CharField(blank=True, db_column='Other_sexual_orientation__c', max_length=30, null=True, verbose_name='Other sexual orientation')), - ('household_type', salesforce.fields.CharField(blank=True, choices=[('Single Female Headed Family', 'Single Female Headed Family'), ('Single Male Headed Family', 'Single Male Headed Family'), ('Dual Headed Family', 'Dual Headed Family')], db_column='Household_type__c', help_text='Which best describes your family? (Check one)\r\nFamily includes, but is not limited to the following—regardless of actual or perceived sexual orientation, gender identity, or marital status—a single person or a group of persons residing together.', max_length=255, null=True, verbose_name='Which best describes your family?')), - ('income_certification', salesforce.fields.CharField(blank=True, choices=[('CalWorks', 'CalWorks'), ('Food Stamps', 'Food Stamps'), ('Medi-CAL', 'Medi-CAL'), ('Tax Return (most recent)', 'Tax Return (most recent)'), ('Unemployment (check stub)', 'Unemployment (check stub)'), ('SSI**', 'SSI**'), ('Payroll Stub**', 'Payroll Stub**'), ('Other (i.e. public housing/foster care)**', 'Other (i.e. public housing/foster care)**'), ('Self-certified', 'Self-certified')], db_column='Income_Certification__c', help_text='**current-within 2 months', max_length=4099, null=True, verbose_name='Income Certification')), - ('estimated_income', salesforce.fields.DecimalField(blank=True, db_column='Estimated_income__c', decimal_places=2, help_text='Total estimated income for next 12 months for all adult members.', max_digits=18, null=True, verbose_name='Estimated income')), - ('family_size', salesforce.fields.CharField(blank=True, choices=[('1 person', '1 person'), ('2 persons', '2 persons'), ('3 persons', '3 persons'), ('4 persons', '4 persons'), ('5 persons', '5 persons'), ('6 persons', '6 persons'), ('7 persons', '7 persons'), ('8 persons', '8 persons'), ('9+ persons', '9+ persons')], db_column='Family_size__c', help_text='Number of persons living in your family (including yourself):', max_length=255, null=True, verbose_name='Family size')), - ('current_income_information', salesforce.fields.CharField(blank=True, choices=[('Extremely Low Income $0 - 27,650 (1 person)', 'Extremely Low Income $0 - 27,650 (1 person)'), ('Low Income $27,651 - 46,100 (1 person)', 'Low Income $27,651 - 46,100 (1 person)'), ('Moderate Income $46,101 - 73,750 (1 person)', 'Moderate Income $46,101 - 73,750 (1 person)'), ('Above Moderate Income $73,751 or greater (1 person)', 'Above Moderate Income $73,751 or greater (1 person)'), ('Extremely Low Income $0 - 31,600 (2 persons)', 'Extremely Low Income $0 - 31,600 (2 persons)'), ('Low Income $31,601 - 52,650 (2 persons)', 'Low Income $31,601 - 52,650 (2 persons)'), ('Moderate Income $52,651 - 84,300 (2 persons)', 'Moderate Income $52,651 - 84,300 (2 persons)'), ('Above Moderate Income $84,301 or greater (2 persons)', 'Above Moderate Income $84,301 or greater (2 persons)'), ('Extremely Low Income $0 - 35,550 (3 persons)', 'Extremely Low Income $0 - 35,550 (3 persons)'), ('Low Income $35,551 - 59,250 (3 persons)', 'Low Income $35,551 - 59,250 (3 persons)'), ('Moderate Income $59,251 - 94,850 (3 persons)', 'Moderate Income $59,251 - 94,850 (3 persons)'), ('Above Moderate Income $94,851 or greater (3 persons)', 'Above Moderate Income $94,851 or greater (3 persons)'), ('Extremely Low Income $0 - 39,500 (4 persons)', 'Extremely Low Income $0 - 39,500 (4 persons)'), ('Low Income $39,501 - 65,800 (4 persons)', 'Low Income $39,501 - 65,800 (4 persons)'), ('Moderate Income $65,801 - 105,350 (4 persons)', 'Moderate Income $65,801 - 105,350 (4 persons)'), ('Above Moderate Income $105,351 or greater (4 persons)', 'Above Moderate Income $105,351 or greater (4 persons)'), ('Extremely Low Income $0 - 42,700 (5 persons)', 'Extremely Low Income $0 - 42,700 (5 persons)'), ('Low Income $42,701 - 71,100 (5 persons)', 'Low Income $42,701 - 71,100 (5 persons)'), ('Moderate Income $71,101 - 113,800 (5 persons)', 'Moderate Income $71,101 - 113,800 (5 persons)'), ('Above Moderate Income $113,801 or greater (5 persons)', 'Above Moderate Income $113,801 or greater (5 persons)'), ('Extremely Low Income $0 - 45,850 (6 persons)', 'Extremely Low Income $0 - 45,850 (6 persons)'), ('Low Income $45,851 - 76,350 (6 persons)', 'Low Income $45,851 - 76,350 (6 persons)'), ('Moderate Income $76,351 - 122,250 (6 persons)', 'Moderate Income $76,351 - 122,250 (6 persons)'), ('Above Moderate Income $122,251 or greater (6 persons)', 'Above Moderate Income $122,251 or greater (6 persons)'), ('Extremely Low Income $0 - 49,000 (7 persons)', 'Extremely Low Income $0 - 49,000 (7 persons)'), ('Low Income $49,001 - 81,600 (7 persons)', 'Low Income $49,001 - 81,600 (7 persons)'), ('Moderate Income $81,601 - 130,650 (7 persons)', 'Moderate Income $81,601 - 130,650 (7 persons)'), ('Above Moderate Income $130,651 or greater (7 persons)', 'Above Moderate Income $130,651 or greater (7 persons)'), ('Extremely Low Income $0 - 52,150 (8 persons)', 'Extremely Low Income $0 - 52,150 (8 persons)'), ('Low Income $52,151 - 86,900 (8 persons)', 'Low Income $52,151 - 86,900 (8 persons)'), ('Moderate Income $86,901 - 139,100 (8 persons)', 'Moderate Income $86,901 - 139,100 (8 persons)'), ('Above Moderate Income $139,101 or greater (8 persons)', 'Above Moderate Income $139,101 or greater (8 persons)')], db_column='Current_Income_Information__c', max_length=255, null=True, verbose_name='Current Income Information')), - ('if_self_certified_please_explain', salesforce.fields.TextField(blank=True, db_column='If_self_certified_please_explain__c', null=True, verbose_name='If self-certified, please explain:')), - ('contact_ethnicity', salesforce.fields.CharField(blank=True, db_column='Contact_Ethnicity__c', help_text='DO NOT EDIT - AUTO-POPULATED BY SYSTEM', max_length=100, null=True, verbose_name='Contact - Ethnicity')), - ('notes', salesforce.fields.TextField(blank=True, null=True)), - ('interview_date', salesforce.fields.DateTimeField(blank=True, db_column='Interview_Date__c', help_text="This is the interview date and time that the student signed up for. Empty means that the student did not sign up for an interview. Having an interview date does not mean that the student showed up for the interview, only that they RSVP'ed.", null=True, verbose_name='Interview Date')), - ('returner', salesforce.fields.BooleanField(default=False, verbose_name='Returner?')), - ('temp_returner', salesforce.fields.BooleanField(db_column='Temp_Returner__c', default=salesforce.backend.operations.DefaultedOnCreate(), help_text='This is a temporary field that determines if a student is a returner based on their response to this question on the application. Once we complete migrating all of our past data into Salesforce, this field will be deleted.', verbose_name='Returner? (temp)')), - ('origin_school', salesforce.fields.CharField(blank=True, db_column='Origin_School__c', max_length=1300, null=True, verbose_name='School attended by this student')), - ('parent_phone', salesforce.fields.CharField(blank=True, db_column='Parent_Phone__c', max_length=1300, null=True, verbose_name='Parent Phone')), - ('parent_email', salesforce.fields.CharField(blank=True, db_column='Parent_Email__c', max_length=1300, null=True, verbose_name='Parent Email')), - ('class_offering', salesforce.fields.ForeignKey(db_column='Class_Offering__c', on_delete=django.db.models.deletion.DO_NOTHING, to='home.ClassOffering')), - ('contact', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='classenrollment_contact_set', to='home.Contact')), - ('created_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='classenrollment_createdby_set', to='home.User')), - ('last_modified_by', salesforce.fields.ForeignKey(on_delete=django.db.models.deletion.DO_NOTHING, related_name='classenrollment_lastmodifiedby_set', to='home.User')), - ('parent_contact', salesforce.fields.ForeignKey(blank=True, db_column='Parent_Contact__c', null=True, on_delete=django.db.models.deletion.DO_NOTHING, related_name='classenrollment_parentcontact_set', to='home.Contact')), + ( + "id", + salesforce.fields.SalesforceAutoField( + auto_created=True, + db_column="Id", + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "is_deleted", + salesforce.fields.BooleanField( + default=False, verbose_name="Deleted" + ), + ), + ( + "name", + salesforce.fields.CharField( + max_length=80, verbose_name="Class Enrollment #" + ), + ), + ("created_date", salesforce.fields.DateTimeField()), + ("last_modified_date", salesforce.fields.DateTimeField()), + ("system_modstamp", salesforce.fields.DateTimeField()), + ( + "last_activity_date", + salesforce.fields.DateField(blank=True, null=True), + ), + ( + "last_viewed_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "last_referenced_date", + salesforce.fields.DateTimeField(blank=True, null=True), + ), + ( + "role", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Student", "Student"), + ("TA", "TA"), + ("Volunteer", "Volunteer"), + ], + max_length=255, + null=True, + ), + ), + ( + "status", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Applied", "Applied"), + ("Waitlisted", "Waitlisted"), + ("Enrolled", "Enrolled"), + ("Completed-Course", "Completed-Course"), + ("Withdrew-Application", "Withdrew-Application"), + ("Rejected", "Rejected"), + ("Dropped", "Dropped"), + ], + max_length=255, + null=True, + ), + ), + ( + "in_current_semester", + salesforce.fields.BooleanField( + db_column="In_current_semester__c", + default=False, + verbose_name="In current semester?", + ), + ), + ( + "attended_family_orientation", + salesforce.fields.BooleanField( + db_column="Attended_Family_Orientation__c", + default=salesforce.backend.operations.DefaultedOnCreate(), + verbose_name="Attended Family Orientation", + ), + ), + ( + "withdrew_application_detail", + salesforce.fields.CharField( + blank=True, + choices=[ + ( + "Didn't show up for interview", + "Didn't show up for interview", + ), + ("Acceptance-offer-rejected", "Acceptance-offer-rejected"), + ("Didn’t show up for class", "Didn’t show up for class"), + ("Dropped in first 2 weeks", "Dropped in first 2 weeks"), + ("Withdrew before interview", "Withdrew before interview"), + ("Class Cancelled", "Class Cancelled"), + ], + db_column="Withdrew_Application_Detail__c", + help_text='"Dropped in first 2 weeks" means that they showed up for class but decided to drop within the first 2 weeks.', + max_length=255, + null=True, + verbose_name="Withdrew-Application Detail", + ), + ), + ( + "contact_race", + salesforce.fields.CharField( + blank=True, + db_column="Contact_Race__c", + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_length=100, + null=True, + verbose_name="Contact - Race", + ), + ), + ( + "contact_gender", + salesforce.fields.CharField( + blank=True, + db_column="Contact_Gender__c", + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_length=30, + null=True, + verbose_name="Contact - Gender", + ), + ), + ( + "attended_interview", + salesforce.fields.BooleanField( + db_column="Attended_Interview__c", + default=salesforce.backend.operations.DefaultedOnCreate(), + help_text="Check if the student attended the default student admissions interview event. Note: Do not check this field if the student attended a makeup interview.", + verbose_name="Attended Interview", + ), + ), + ( + "attended_makeup_interview", + salesforce.fields.BooleanField( + db_column="Attended_Makeup_Interview__c", + default=salesforce.backend.operations.DefaultedOnCreate(), + help_text="Check if the student did not attend the default interview date, but attended a makeup session.", + verbose_name="Attended Makeup Interview", + ), + ), + ( + "cultural_affiliation_or_nationality", + salesforce.fields.CharField( + blank=True, + db_column="Cultural_Affiliation_or_Nationality__c", + help_text="(optional)", + max_length=100, + null=True, + verbose_name="Cultural Affiliation or Nationality", + ), + ), + ( + "sex_at_birth", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Female", "Female"), + ("Male", "Male"), + ("Decline to answer", "Decline to answer"), + ], + db_column="Sex_at_birth__c", + help_text="(Check one)", + max_length=255, + null=True, + verbose_name="What was your sex at birth?", + ), + ), + ( + "sexual_orientation", + salesforce.fields.CharField( + blank=True, + choices=[ + ("Bisexual", "Bisexual"), + ( + "Gay / Lesbian / Same-Gender Loving", + "Gay / Lesbian / Same-Gender Loving", + ), + ("Questioning / Unsure", "Questioning / Unsure"), + ("Straight / Heterosexual", "Straight / Heterosexual"), + ("Not Listed.", "Not Listed."), + ("Decline to answer", "Decline to answer"), + ], + db_column="Sexual_orientation__c", + help_text="How do you describe your sexual orientation or sexual identity?", + max_length=255, + null=True, + verbose_name="Sexual orientation or sexual identity", + ), + ), + ( + "other_sexual_orientation", + salesforce.fields.CharField( + blank=True, + db_column="Other_sexual_orientation__c", + max_length=30, + null=True, + verbose_name="Other sexual orientation", + ), + ), + ( + "household_type", + salesforce.fields.CharField( + blank=True, + choices=[ + ( + "Single Female Headed Family", + "Single Female Headed Family", + ), + ("Single Male Headed Family", "Single Male Headed Family"), + ("Dual Headed Family", "Dual Headed Family"), + ], + db_column="Household_type__c", + help_text="Which best describes your family? (Check one)\r\nFamily includes, but is not limited to the following—regardless of actual or perceived sexual orientation, gender identity, or marital status—a single person or a group of persons residing together.", + max_length=255, + null=True, + verbose_name="Which best describes your family?", + ), + ), + ( + "income_certification", + salesforce.fields.CharField( + blank=True, + choices=[ + ("CalWorks", "CalWorks"), + ("Food Stamps", "Food Stamps"), + ("Medi-CAL", "Medi-CAL"), + ("Tax Return (most recent)", "Tax Return (most recent)"), + ("Unemployment (check stub)", "Unemployment (check stub)"), + ("SSI**", "SSI**"), + ("Payroll Stub**", "Payroll Stub**"), + ( + "Other (i.e. public housing/foster care)**", + "Other (i.e. public housing/foster care)**", + ), + ("Self-certified", "Self-certified"), + ], + db_column="Income_Certification__c", + help_text="**current-within 2 months", + max_length=4099, + null=True, + verbose_name="Income Certification", + ), + ), + ( + "estimated_income", + salesforce.fields.DecimalField( + blank=True, + db_column="Estimated_income__c", + decimal_places=2, + help_text="Total estimated income for next 12 months for all adult members.", + max_digits=18, + null=True, + verbose_name="Estimated income", + ), + ), + ( + "family_size", + salesforce.fields.CharField( + blank=True, + choices=[ + ("1 person", "1 person"), + ("2 persons", "2 persons"), + ("3 persons", "3 persons"), + ("4 persons", "4 persons"), + ("5 persons", "5 persons"), + ("6 persons", "6 persons"), + ("7 persons", "7 persons"), + ("8 persons", "8 persons"), + ("9+ persons", "9+ persons"), + ], + db_column="Family_size__c", + help_text="Number of persons living in your family (including yourself):", + max_length=255, + null=True, + verbose_name="Family size", + ), + ), + ( + "current_income_information", + salesforce.fields.CharField( + blank=True, + choices=[ + ( + "Extremely Low Income $0 - 27,650 (1 person)", + "Extremely Low Income $0 - 27,650 (1 person)", + ), + ( + "Low Income $27,651 - 46,100 (1 person)", + "Low Income $27,651 - 46,100 (1 person)", + ), + ( + "Moderate Income $46,101 - 73,750 (1 person)", + "Moderate Income $46,101 - 73,750 (1 person)", + ), + ( + "Above Moderate Income $73,751 or greater (1 person)", + "Above Moderate Income $73,751 or greater (1 person)", + ), + ( + "Extremely Low Income $0 - 31,600 (2 persons)", + "Extremely Low Income $0 - 31,600 (2 persons)", + ), + ( + "Low Income $31,601 - 52,650 (2 persons)", + "Low Income $31,601 - 52,650 (2 persons)", + ), + ( + "Moderate Income $52,651 - 84,300 (2 persons)", + "Moderate Income $52,651 - 84,300 (2 persons)", + ), + ( + "Above Moderate Income $84,301 or greater (2 persons)", + "Above Moderate Income $84,301 or greater (2 persons)", + ), + ( + "Extremely Low Income $0 - 35,550 (3 persons)", + "Extremely Low Income $0 - 35,550 (3 persons)", + ), + ( + "Low Income $35,551 - 59,250 (3 persons)", + "Low Income $35,551 - 59,250 (3 persons)", + ), + ( + "Moderate Income $59,251 - 94,850 (3 persons)", + "Moderate Income $59,251 - 94,850 (3 persons)", + ), + ( + "Above Moderate Income $94,851 or greater (3 persons)", + "Above Moderate Income $94,851 or greater (3 persons)", + ), + ( + "Extremely Low Income $0 - 39,500 (4 persons)", + "Extremely Low Income $0 - 39,500 (4 persons)", + ), + ( + "Low Income $39,501 - 65,800 (4 persons)", + "Low Income $39,501 - 65,800 (4 persons)", + ), + ( + "Moderate Income $65,801 - 105,350 (4 persons)", + "Moderate Income $65,801 - 105,350 (4 persons)", + ), + ( + "Above Moderate Income $105,351 or greater (4 persons)", + "Above Moderate Income $105,351 or greater (4 persons)", + ), + ( + "Extremely Low Income $0 - 42,700 (5 persons)", + "Extremely Low Income $0 - 42,700 (5 persons)", + ), + ( + "Low Income $42,701 - 71,100 (5 persons)", + "Low Income $42,701 - 71,100 (5 persons)", + ), + ( + "Moderate Income $71,101 - 113,800 (5 persons)", + "Moderate Income $71,101 - 113,800 (5 persons)", + ), + ( + "Above Moderate Income $113,801 or greater (5 persons)", + "Above Moderate Income $113,801 or greater (5 persons)", + ), + ( + "Extremely Low Income $0 - 45,850 (6 persons)", + "Extremely Low Income $0 - 45,850 (6 persons)", + ), + ( + "Low Income $45,851 - 76,350 (6 persons)", + "Low Income $45,851 - 76,350 (6 persons)", + ), + ( + "Moderate Income $76,351 - 122,250 (6 persons)", + "Moderate Income $76,351 - 122,250 (6 persons)", + ), + ( + "Above Moderate Income $122,251 or greater (6 persons)", + "Above Moderate Income $122,251 or greater (6 persons)", + ), + ( + "Extremely Low Income $0 - 49,000 (7 persons)", + "Extremely Low Income $0 - 49,000 (7 persons)", + ), + ( + "Low Income $49,001 - 81,600 (7 persons)", + "Low Income $49,001 - 81,600 (7 persons)", + ), + ( + "Moderate Income $81,601 - 130,650 (7 persons)", + "Moderate Income $81,601 - 130,650 (7 persons)", + ), + ( + "Above Moderate Income $130,651 or greater (7 persons)", + "Above Moderate Income $130,651 or greater (7 persons)", + ), + ( + "Extremely Low Income $0 - 52,150 (8 persons)", + "Extremely Low Income $0 - 52,150 (8 persons)", + ), + ( + "Low Income $52,151 - 86,900 (8 persons)", + "Low Income $52,151 - 86,900 (8 persons)", + ), + ( + "Moderate Income $86,901 - 139,100 (8 persons)", + "Moderate Income $86,901 - 139,100 (8 persons)", + ), + ( + "Above Moderate Income $139,101 or greater (8 persons)", + "Above Moderate Income $139,101 or greater (8 persons)", + ), + ], + db_column="Current_Income_Information__c", + max_length=255, + null=True, + verbose_name="Current Income Information", + ), + ), + ( + "if_self_certified_please_explain", + salesforce.fields.TextField( + blank=True, + db_column="If_self_certified_please_explain__c", + null=True, + verbose_name="If self-certified, please explain:", + ), + ), + ( + "contact_ethnicity", + salesforce.fields.CharField( + blank=True, + db_column="Contact_Ethnicity__c", + help_text="DO NOT EDIT - AUTO-POPULATED BY SYSTEM", + max_length=100, + null=True, + verbose_name="Contact - Ethnicity", + ), + ), + ("notes", salesforce.fields.TextField(blank=True, null=True)), + ( + "interview_date", + salesforce.fields.DateTimeField( + blank=True, + db_column="Interview_Date__c", + help_text="This is the interview date and time that the student signed up for. Empty means that the student did not sign up for an interview. Having an interview date does not mean that the student showed up for the interview, only that they RSVP'ed.", + null=True, + verbose_name="Interview Date", + ), + ), + ( + "returner", + salesforce.fields.BooleanField( + default=False, verbose_name="Returner?" + ), + ), + ( + "temp_returner", + salesforce.fields.BooleanField( + db_column="Temp_Returner__c", + default=salesforce.backend.operations.DefaultedOnCreate(), + help_text="This is a temporary field that determines if a student is a returner based on their response to this question on the application. Once we complete migrating all of our past data into Salesforce, this field will be deleted.", + verbose_name="Returner? (temp)", + ), + ), + ( + "origin_school", + salesforce.fields.CharField( + blank=True, + db_column="Origin_School__c", + max_length=1300, + null=True, + verbose_name="School attended by this student", + ), + ), + ( + "parent_phone", + salesforce.fields.CharField( + blank=True, + db_column="Parent_Phone__c", + max_length=1300, + null=True, + verbose_name="Parent Phone", + ), + ), + ( + "parent_email", + salesforce.fields.CharField( + blank=True, + db_column="Parent_Email__c", + max_length=1300, + null=True, + verbose_name="Parent Email", + ), + ), + ( + "class_offering", + salesforce.fields.ForeignKey( + db_column="Class_Offering__c", + on_delete=django.db.models.deletion.DO_NOTHING, + to="home.ClassOffering", + ), + ), + ( + "contact", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classenrollment_contact_set", + to="home.Contact", + ), + ), + ( + "created_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classenrollment_createdby_set", + to="home.User", + ), + ), + ( + "last_modified_by", + salesforce.fields.ForeignKey( + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classenrollment_lastmodifiedby_set", + to="home.User", + ), + ), + ( + "parent_contact", + salesforce.fields.ForeignKey( + blank=True, + db_column="Parent_Contact__c", + null=True, + on_delete=django.db.models.deletion.DO_NOTHING, + related_name="classenrollment_parentcontact_set", + to="home.Contact", + ), + ), ], options={ - 'verbose_name': 'Class Enrollment', - 'verbose_name_plural': 'Class Enrollments', - 'db_table': 'Class_Enrollment__c', - 'abstract': False, - 'base_manager_name': 'objects', + "verbose_name": "Class Enrollment", + "verbose_name_plural": "Class Enrollments", + "db_table": "Class_Enrollment__c", + "abstract": False, + "base_manager_name": "objects", }, ), migrations.AddField( - model_name='attendance', - name='classroom', - field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='attendance_classroom', to='home.Classroom'), + model_name="attendance", + name="classroom", + field=models.ForeignKey( + default=None, + on_delete=django.db.models.deletion.CASCADE, + related_name="attendance_classroom", + to="home.Classroom", + ), ), migrations.AddField( - model_name='attendance', - name='session', - field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='session', to='home.Session'), + model_name="attendance", + name="session", + field=models.ForeignKey( + default=None, + on_delete=django.db.models.deletion.CASCADE, + related_name="session", + to="home.Session", + ), ), migrations.AddField( - model_name='attendance', - name='student', - field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='student', to=settings.AUTH_USER_MODEL), + model_name="attendance", + name="student", + field=models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="student", + to=settings.AUTH_USER_MODEL, + ), ), migrations.CreateModel( - name='Announcement', + name="Announcement", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.CharField(max_length=240, unique=True)), - ('announcement', models.TextField(max_length=2500)), - ('posted', models.DateTimeField(auto_now=True, db_index=True)), - ('email_recipients', models.BooleanField(default=False)), - ('created_by', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='user', to=settings.AUTH_USER_MODEL)), - ('recipient_classrooms', models.ManyToManyField(related_name='recipient_classroom', to='home.Classroom')), - ('recipient_groups', models.ManyToManyField(related_name='user_groups', to='auth.Group')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.CharField(max_length=240, unique=True)), + ("announcement", models.TextField(max_length=2500)), + ("posted", models.DateTimeField(auto_now=True, db_index=True)), + ("email_recipients", models.BooleanField(default=False)), + ( + "created_by", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="user", + to=settings.AUTH_USER_MODEL, + ), + ), + ( + "recipient_classrooms", + models.ManyToManyField( + related_name="recipient_classroom", to="home.Classroom" + ), + ), + ( + "recipient_groups", + models.ManyToManyField(related_name="user_groups", to="auth.Group"), + ), ], ), ] diff --git a/home/migrations/0002_add_groups.py b/home/migrations/0002_add_groups.py index 9cf21f4..3af5c2a 100644 --- a/home/migrations/0002_add_groups.py +++ b/home/migrations/0002_add_groups.py @@ -18,9 +18,7 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), ("auth", "0011_update_proxy_permissions"), - ('home', '0001_initial'), + ("home", "0001_initial"), ] - operations = [ - migrations.RunPython(add_groups), - ] + operations = [migrations.RunPython(add_groups)] diff --git a/home/migrations/0003_announcementdistribution.py b/home/migrations/0003_announcementdistribution.py index 9c37bb8..6cdfdfc 100644 --- a/home/migrations/0003_announcementdistribution.py +++ b/home/migrations/0003_announcementdistribution.py @@ -9,17 +9,39 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('home', '0002_add_groups'), + ("home", "0002_add_groups"), ] operations = [ migrations.CreateModel( - name='AnnouncementDistribution', + name="AnnouncementDistribution", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('dismissed', models.BooleanField(default=False)), - ('announcement', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='announcement_distributed', to='home.Announcement')), - ('user', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='announcement_user', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("dismissed", models.BooleanField(default=False)), + ( + "announcement", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="announcement_distributed", + to="home.Announcement", + ), + ), + ( + "user", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="announcement_user", + to=settings.AUTH_USER_MODEL, + ), + ), ], - ), + ) ] diff --git a/home/migrations/0004_auto_20190802_0126.py b/home/migrations/0004_auto_20190802_0126.py index 9308a19..aadce40 100644 --- a/home/migrations/0004_auto_20190802_0126.py +++ b/home/migrations/0004_auto_20190802_0126.py @@ -7,41 +7,108 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0003_announcementdistribution'), - ] + dependencies = [("home", "0003_announcementdistribution")] operations = [ migrations.AddField( - model_name='session', - name='classroom', - field=models.ForeignKey(default=None, on_delete=django.db.models.deletion.CASCADE, related_name='classroom_session', to='home.Classroom'), + model_name="session", + name="classroom", + field=models.ForeignKey( + default=None, + on_delete=django.db.models.deletion.CASCADE, + related_name="classroom_session", + to="home.Classroom", + ), ), migrations.AddField( - model_name='session', - name='date', - field=models.DateField(default='1901-01-01'), + model_name="session", + name="date", + field=models.DateField(default="1901-01-01"), ), migrations.AlterField( - model_name='contact', - name='race', - field=salesforce.fields.CharField(blank=True, choices=[('American Indian/Alaskan Native', 'American Indian/Alaskan Native'), ('Asian', 'Asian'), ('Black/African American', 'Black/African American'), ('Native Hawaiian/Other Pacific Islander', 'Native Hawaiian/Other Pacific Islander'), ('White', 'White'), ('American Indian/Alaskan Native AND Black/African American', 'American Indian/Alaskan Native AND Black/African American'), ('American Indian/Alaskan Native AND White', 'American Indian/Alaskan Native AND White'), ('Asian AND White', 'Asian AND White'), ('Black/African American AND White', 'Black/African American AND White'), ('Other/Multiracial', 'Other/Multiracial')], max_length=255, null=True, verbose_name='Which best describes your race?'), + model_name="contact", + name="race", + field=salesforce.fields.CharField( + blank=True, + choices=[ + ( + "American Indian/Alaskan Native", + "American Indian/Alaskan Native", + ), + ("Asian", "Asian"), + ("Black/African American", "Black/African American"), + ( + "Native Hawaiian/Other Pacific Islander", + "Native Hawaiian/Other Pacific Islander", + ), + ("White", "White"), + ( + "American Indian/Alaskan Native AND Black/African American", + "American Indian/Alaskan Native AND Black/African American", + ), + ( + "American Indian/Alaskan Native AND White", + "American Indian/Alaskan Native AND White", + ), + ("Asian AND White", "Asian AND White"), + ( + "Black/African American AND White", + "Black/African American AND White", + ), + ("Other/Multiracial", "Other/Multiracial"), + ], + max_length=255, + null=True, + verbose_name="Which best describes your race?", + ), ), migrations.AlterField( - model_name='contact', - name='which_best_describes_your_ethnicity', - field=salesforce.fields.CharField(blank=True, choices=[('Hispanic/Latinx', 'Hispanic/Latinx'), ('Not Hispanic/Latinx', 'Not Hispanic/Latinx')], db_column='Which_best_describes_your_ethnicity__c', max_length=255, null=True, verbose_name='Which best describes your ethnicity?'), + model_name="contact", + name="which_best_describes_your_ethnicity", + field=salesforce.fields.CharField( + blank=True, + choices=[ + ("Hispanic/Latinx", "Hispanic/Latinx"), + ("Not Hispanic/Latinx", "Not Hispanic/Latinx"), + ], + db_column="Which_best_describes_your_ethnicity__c", + max_length=255, + null=True, + verbose_name="Which best describes your ethnicity?", + ), ), migrations.CreateModel( - name='Resource', + name="Resource", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('title', models.TextField(default='No Title', max_length=240)), - ('description', models.TextField(max_length=2000)), - ('link', models.URLField(default=None, null=True)), - ('file', models.FileField(default=None, null=True, upload_to='')), - ('classroom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='classroom_resource', to='home.Classroom')), - ('session', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='session_resource', to='home.Session')), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ("title", models.TextField(default="No Title", max_length=240)), + ("description", models.TextField(max_length=2000)), + ("link", models.URLField(default=None, null=True)), + ("file", models.FileField(default=None, null=True, upload_to="")), + ( + "classroom", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="classroom_resource", + to="home.Classroom", + ), + ), + ( + "session", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="session_resource", + to="home.Session", + ), + ), ], ), ] diff --git a/home/migrations/0005_userprofile_in_classroom.py b/home/migrations/0005_userprofile_in_classroom.py index 55905f7..f92ed54 100644 --- a/home/migrations/0005_userprofile_in_classroom.py +++ b/home/migrations/0005_userprofile_in_classroom.py @@ -5,14 +5,12 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0004_auto_20190802_0126'), - ] + dependencies = [("home", "0004_auto_20190802_0126")] operations = [ migrations.AddField( - model_name='userprofile', - name='in_classroom', + model_name="userprofile", + name="in_classroom", field=models.BooleanField(default=False), - ), + ) ] diff --git a/home/migrations/0006_session_title.py b/home/migrations/0006_session_title.py index 3c47ea6..96ad9e6 100644 --- a/home/migrations/0006_session_title.py +++ b/home/migrations/0006_session_title.py @@ -5,14 +5,12 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0005_userprofile_in_classroom'), - ] + dependencies = [("home", "0005_userprofile_in_classroom")] operations = [ migrations.AddField( - model_name='session', - name='title', - field=models.CharField(default='No Title', max_length=240), - ), + model_name="session", + name="title", + field=models.CharField(default="No Title", max_length=240), + ) ] diff --git a/home/migrations/0007_auto_20190803_1930.py b/home/migrations/0007_auto_20190803_1930.py index 86ba73a..f0d8bf7 100644 --- a/home/migrations/0007_auto_20190803_1930.py +++ b/home/migrations/0007_auto_20190803_1930.py @@ -5,39 +5,37 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0006_session_title'), - ] + dependencies = [("home", "0006_session_title")] operations = [ migrations.AddField( - model_name='classroom', - name='forum', + model_name="classroom", + name="forum", field=models.URLField(default=None, null=True), ), migrations.AddField( - model_name='classroom', - name='forum_title', + model_name="classroom", + name="forum_title", field=models.CharField(default=None, max_length=240, null=True), ), migrations.AlterField( - model_name='resource', - name='file', - field=models.FileField(default=None, null=True, upload_to='documents/'), + model_name="resource", + name="file", + field=models.FileField(default=None, null=True, upload_to="documents/"), ), migrations.AlterField( - model_name='session', - name='activity', - field=models.FileField(default=None, upload_to='documents/'), + model_name="session", + name="activity", + field=models.FileField(default=None, upload_to="documents/"), ), migrations.AlterField( - model_name='session', - name='lecture', - field=models.FileField(default=None, upload_to='documents/'), + model_name="session", + name="lecture", + field=models.FileField(default=None, upload_to="documents/"), ), migrations.AlterField( - model_name='session', - name='lesson_plan', - field=models.FileField(default=None, upload_to='documents/'), + model_name="session", + name="lesson_plan", + field=models.FileField(default=None, upload_to="documents/"), ), ] diff --git a/home/migrations/0008_remove_userprofile_in_classroom.py b/home/migrations/0008_remove_userprofile_in_classroom.py index bb3579b..1de923f 100644 --- a/home/migrations/0008_remove_userprofile_in_classroom.py +++ b/home/migrations/0008_remove_userprofile_in_classroom.py @@ -5,13 +5,6 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0007_auto_20190803_1930'), - ] + dependencies = [("home", "0007_auto_20190803_1930")] - operations = [ - migrations.RemoveField( - model_name='userprofile', - name='in_classroom', - ), - ] + operations = [migrations.RemoveField(model_name="userprofile", name="in_classroom")] diff --git a/home/migrations/0009_auto_20190804_2253.py b/home/migrations/0009_auto_20190804_2253.py index 7faed89..2844cc2 100644 --- a/home/migrations/0009_auto_20190804_2253.py +++ b/home/migrations/0009_auto_20190804_2253.py @@ -9,38 +9,61 @@ class Migration(migrations.Migration): dependencies = [ migrations.swappable_dependency(settings.AUTH_USER_MODEL), - ('home', '0008_remove_userprofile_in_classroom'), + ("home", "0008_remove_userprofile_in_classroom"), ] operations = [ - migrations.RemoveField( - model_name='classroom', - name='students', - ), - migrations.RemoveField( - model_name='classroom', - name='teacher', - ), - migrations.RemoveField( - model_name='classroom', - name='teacher_assistant', - ), - migrations.RemoveField( - model_name='classroom', - name='volunteers', - ), + migrations.RemoveField(model_name="classroom", name="students"), + migrations.RemoveField(model_name="classroom", name="teacher"), + migrations.RemoveField(model_name="classroom", name="teacher_assistant"), + migrations.RemoveField(model_name="classroom", name="volunteers"), migrations.CreateModel( - name='ClassroomMembership', + name="ClassroomMembership", fields=[ - ('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')), - ('membership_type', models.CharField(choices=[('teacher', 'teacher'), ('teacher_assistant', 'teacher_assistant'), ('student', 'student'), ('volunteer', 'volunteer')], max_length=240)), - ('classroom', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='membership_classroom', to='home.Classroom')), - ('member', models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='classroom_member', to=settings.AUTH_USER_MODEL)), + ( + "id", + models.AutoField( + auto_created=True, + primary_key=True, + serialize=False, + verbose_name="ID", + ), + ), + ( + "membership_type", + models.CharField( + choices=[ + ("teacher", "teacher"), + ("teacher_assistant", "teacher_assistant"), + ("student", "student"), + ("volunteer", "volunteer"), + ], + max_length=240, + ), + ), + ( + "classroom", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="membership_classroom", + to="home.Classroom", + ), + ), + ( + "member", + models.ForeignKey( + on_delete=django.db.models.deletion.CASCADE, + related_name="classroom_member", + to=settings.AUTH_USER_MODEL, + ), + ), ], ), migrations.AddField( - model_name='classroom', - name='members', - field=models.ManyToManyField(through='home.ClassroomMembership', to=settings.AUTH_USER_MODEL), + model_name="classroom", + name="members", + field=models.ManyToManyField( + through="home.ClassroomMembership", to=settings.AUTH_USER_MODEL + ), ), ] diff --git a/home/migrations/0010_auto_20190806_1917.py b/home/migrations/0010_auto_20190806_1917.py index 2e51803..507f378 100644 --- a/home/migrations/0010_auto_20190806_1917.py +++ b/home/migrations/0010_auto_20190806_1917.py @@ -6,34 +6,40 @@ class Migration(migrations.Migration): - dependencies = [ - ('home', '0009_auto_20190804_2253'), - ] + dependencies = [("home", "0009_auto_20190804_2253")] operations = [ migrations.AlterField( - model_name='form', - name='form', + model_name="form", + name="form", field=models.FileField(upload_to=home.models.models.upload_to), ), migrations.AlterField( - model_name='resource', - name='file', - field=models.FileField(default=None, null=True, upload_to=home.models.models.upload_to), + model_name="resource", + name="file", + field=models.FileField( + default=None, null=True, upload_to=home.models.models.upload_to + ), ), migrations.AlterField( - model_name='session', - name='activity', - field=models.FileField(default=None, upload_to=home.models.models.upload_to), + model_name="session", + name="activity", + field=models.FileField( + default=None, upload_to=home.models.models.upload_to + ), ), migrations.AlterField( - model_name='session', - name='lecture', - field=models.FileField(default=None, upload_to=home.models.models.upload_to), + model_name="session", + name="lecture", + field=models.FileField( + default=None, upload_to=home.models.models.upload_to + ), ), migrations.AlterField( - model_name='session', - name='lesson_plan', - field=models.FileField(default=None, upload_to=home.models.models.upload_to), + model_name="session", + name="lesson_plan", + field=models.FileField( + default=None, upload_to=home.models.models.upload_to + ), ), ] diff --git a/home/models/models.py b/home/models/models.py index 7d67222..11b4128 100644 --- a/home/models/models.py +++ b/home/models/models.py @@ -9,20 +9,24 @@ from home.choices import * from werkzeug import secure_filename + def get_name(self): return "%s %s" % (self.first_name, self.last_name) + DjangoUser.add_to_class("__str__", get_name) def upload_to(instance, filename): - return '/'.join([ - secure_filename(type(instance).__name__), - strftime('%Y/%m/%d'), - instance.id or '0', - token_urlsafe(8), - secure_filename(filename) - ]) + return "/".join( + [ + secure_filename(type(instance).__name__), + strftime("%Y/%m/%d"), + instance.id or "0", + token_urlsafe(8), + secure_filename(filename), + ] + ) class UserProfile(mdls.Model): @@ -49,15 +53,19 @@ class Classroom(mdls.Model): forum = mdls.URLField(default=None, null=True) def __str__(self): - return "%s" % ( - self.course - ) + return "%s" % (self.course) class ClassroomMembership(mdls.Model): - member = mdls.ForeignKey(DjangoUser, related_name="classroom_member", on_delete=mdls.CASCADE) - classroom = mdls.ForeignKey(Classroom, related_name="membership_classroom", on_delete=mdls.CASCADE) - membership_type = mdls.CharField(max_length=240, choices=CLASSROOM_MEMBERSHIP_CHOICES) + member = mdls.ForeignKey( + DjangoUser, related_name="classroom_member", on_delete=mdls.CASCADE + ) + classroom = mdls.ForeignKey( + Classroom, related_name="membership_classroom", on_delete=mdls.CASCADE + ) + membership_type = mdls.CharField( + max_length=240, choices=CLASSROOM_MEMBERSHIP_CHOICES + ) class Session(mdls.Model): @@ -67,7 +75,12 @@ class Session(mdls.Model): lecture = mdls.FileField(default=None, upload_to=upload_to) video = mdls.URLField(default=None, null=True) activity = mdls.FileField(default=None, upload_to=upload_to) - classroom = mdls.ForeignKey(Classroom, related_name="classroom_session", on_delete=mdls.CASCADE, default=None) + classroom = mdls.ForeignKey( + Classroom, + related_name="classroom_session", + on_delete=mdls.CASCADE, + default=None, + ) date = mdls.DateField(default="1901-01-01") def __str__(self): @@ -79,8 +92,12 @@ class Resource(mdls.Model): description = mdls.TextField(max_length=2000) link = mdls.URLField(default=None, null=True) file = mdls.FileField(default=None, null=True, upload_to=upload_to) - classroom = mdls.ForeignKey(Classroom, related_name="classroom_resource", on_delete=mdls.CASCADE) - session = mdls.ForeignKey(Session, related_name="session_resource", on_delete=mdls.CASCADE) + classroom = mdls.ForeignKey( + Classroom, related_name="classroom_resource", on_delete=mdls.CASCADE + ) + session = mdls.ForeignKey( + Session, related_name="session_resource", on_delete=mdls.CASCADE + ) def __str__(self): return "%s - %s" % (self.title, self.session) @@ -122,19 +139,30 @@ def __str__(self): class AnnouncementDistribution(mdls.Model): - announcement = mdls.ForeignKey(Announcement, related_name="announcement_distributed", on_delete=mdls.CASCADE) - user = mdls.ForeignKey(DjangoUser, related_name="announcement_user", on_delete=mdls.CASCADE) + announcement = mdls.ForeignKey( + Announcement, related_name="announcement_distributed", on_delete=mdls.CASCADE + ) + user = mdls.ForeignKey( + DjangoUser, related_name="announcement_user", on_delete=mdls.CASCADE + ) dismissed = mdls.BooleanField(null=False, default=False) def __str__(self): - return "%s - %s - dismissed: %s" % (self.announcement, self.user, self.dismissed) + return "%s - %s - dismissed: %s" % ( + self.announcement, + self.user, + self.dismissed, + ) class Esign(mdls.Model): name = mdls.CharField(max_length=240, unique=True) template = mdls.URLField() created_by = mdls.ForeignKey( - DjangoUser, related_name="esign_creator_user", on_delete=mdls.CASCADE, default=False + DjangoUser, + related_name="esign_creator_user", + on_delete=mdls.CASCADE, + default=False, ) def __str__(self): @@ -145,7 +173,9 @@ class Form(mdls.Model): name = mdls.CharField(max_length=240, unique=True) description = mdls.TextField(max_length=2500) form = mdls.FileField(upload_to=upload_to) - esign = mdls.ForeignKey(Esign, related_name="esign_form", on_delete=mdls.CASCADE, null=True) + esign = mdls.ForeignKey( + Esign, related_name="esign_form", on_delete=mdls.CASCADE, null=True + ) posted = mdls.DateTimeField(db_index=True, auto_now=True) recipient_groups = mdls.ManyToManyField(Group, related_name="form_user_groups") recipient_classrooms = mdls.ManyToManyField( @@ -160,8 +190,12 @@ def __str__(self): class FormDistribution(mdls.Model): - user = mdls.ForeignKey(DjangoUser, related_name="form_signer", on_delete=mdls.CASCADE) - form = mdls.ForeignKey(Form, related_name="form_to_be_signed", on_delete=mdls.CASCADE) + user = mdls.ForeignKey( + DjangoUser, related_name="form_signer", on_delete=mdls.CASCADE + ) + form = mdls.ForeignKey( + Form, related_name="form_to_be_signed", on_delete=mdls.CASCADE + ) submitted = mdls.BooleanField(null=False, default=False) def __str__(self): @@ -169,12 +203,21 @@ def __str__(self): class Notification(mdls.Model): - user = mdls.ForeignKey(DjangoUser, related_name="notified_user", on_delete=mdls.CASCADE) + user = mdls.ForeignKey( + DjangoUser, related_name="notified_user", on_delete=mdls.CASCADE + ) subject = mdls.CharField(max_length=240) notification = mdls.TextField(max_length=2500) email_recipients = mdls.BooleanField(null=False, default=False) - form = mdls.ForeignKey(Form, related_name="notified_about_form", on_delete=mdls.CASCADE, null=True) - attendance = mdls.ForeignKey(Attendance, related_name="notified_about_attendance", on_delete=mdls.CASCADE, null=True) + form = mdls.ForeignKey( + Form, related_name="notified_about_form", on_delete=mdls.CASCADE, null=True + ) + attendance = mdls.ForeignKey( + Attendance, + related_name="notified_about_attendance", + on_delete=mdls.CASCADE, + null=True, + ) notified = mdls.DateTimeField(db_index=True, auto_now=True) created_by = mdls.ForeignKey( DjangoUser, related_name="notification_user", on_delete=mdls.CASCADE diff --git a/home/templates/home/change_pwd.html b/home/templates/home/change_pwd.html index 669b8f7..c9e5b5a 100644 --- a/home/templates/home/change_pwd.html +++ b/home/templates/home/change_pwd.html @@ -1,32 +1,28 @@ -{% extends "home/home.html" %} -{% load crispy_forms_tags %} +{% extends "home_base.html" %} +{% load static %} {% block content %} -
    - -
    - -

    Change your Password

    -
    Please refer to the email you received to find your temporary password
    - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    - - +
    +
    + {% include "error.html" %} +
    + Please change your password + {% csrf_token %} +
    + Old Password: {{ form.old_password }} +
    +
    + New Password: {{ form.new_password1 }} +
    +
    + Retype Password: {{ form.new_password2 }} +
    + +
    +
    +
    +
    {% endblock content %} diff --git a/home/templates/home/home.html b/home/templates/home/home.html deleted file mode 100644 index 955ccbf..0000000 --- a/home/templates/home/home.html +++ /dev/null @@ -1,74 +0,0 @@ -{% load static %} - - - - Mission Bit - - - - - - - - - - - - -{% block content %} - - -{% endblock %} - - - - diff --git a/home/templates/home/index.html b/home/templates/home/index.html deleted file mode 100644 index 8f13db2..0000000 --- a/home/templates/home/index.html +++ /dev/null @@ -1,68 +0,0 @@ -{% load static %} - - - - - - - - -

    Use This Page to Test Mission Bit Django-Salesforce Functionality

    - - {% if contacts %} -

    Contacts

    -
      - {% for contact in contacts %} -
    • {{ contact.first_name }} {{ contact.last_name }}
    • - {% endfor %} -
    - {% else %} -

    No Salesforce Contacts

    - {% endif %} - - {% if users %} -

    Users

    -
      - {% for user in users %} -
    • {{ user.username }}
    • - {% endfor %} -
    - {% else %} -

    No Salesforce Users

    - {% endif %} - - {% if individuals %} -

    Individuals

    -
      - {% for ind in individuals %} -
    • {{ ind.first_name }}
    • - {% endfor %} -
    - {% else %} -

    No Salesforce Individuals

    - {% endif %} - - {% if classes %} -

    Class Offerings

    -
      - {% for class in classes %} -
    • {{ class.name }} {{ class.course }}
    • - {% endfor %} -
    - {% else %} -

    No Salesforce Class Offerings

    - {% endif %} - - {% if enrollments %} -

    Class Enrollments

    -
      - {% for enrollment in enrollments %} -
    • {{ enrollment.name }} {{ enrollment.contact.name }}
    • - {% endfor %} -
    - {% else %} -

    No Salesforce Class Enrollments

    - {% endif %} - - - diff --git a/home/templates/home/landing_page.html b/home/templates/home/landing_page.html index faece47..8b01880 100644 --- a/home/templates/home/landing_page.html +++ b/home/templates/home/landing_page.html @@ -1,70 +1,60 @@ -{% extends "home/home.html" %} -{% load crispy_forms_tags %} - -{% block content %} -{% if messages %} -{% for message in messages %} -
    - {{ message }} -
    -{% endfor %} -{% endif %} - - - -
    - -
    - -
    -

    Please Log In Or Register with Mission Bit



    -
    -
    -
    -
    -
    Register
    -
    - +{% load static %} + + + + + + + Mission Bit + + + + + + + + + + +
    +
    + +
    +
    + +
    +
    +
    +

    +
    +
    +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    + +
    +
    +
    +
    +

    © Copyright 2019

    +
    +
    -

    Please Log In Or Register

    -
    - Log In
    -
    -

    -- OR --

    - Login with Google
    -
    -

    -- OR --

    - Register
    -
    -{% endblock content %} + + + diff --git a/home/templates/home/logout.html b/home/templates/home/logout.html index 2be116f..c3404cf 100644 --- a/home/templates/home/logout.html +++ b/home/templates/home/logout.html @@ -1,25 +1,19 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} +{% load static %} {% block content %} - - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} -

    You have been logged out

    -
    -
    +
    +
    + +

    You have been logged out


    +
    + +

    +
    + +

    +
    {% endblock content %} diff --git a/home/templates/home/register.html b/home/templates/home/register.html index b484a3a..eb58e51 100644 --- a/home/templates/home/register.html +++ b/home/templates/home/register.html @@ -1,29 +1,61 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} +{% load static %} {% block content %} - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} +
    +
    + {% include "registration_error.html" %} + +
    + {% if registration_type == "student" %} + Register As Mission Bit Student + {% endif %} + {% if registration_type == "volunteer" %} + Register As Mission Bit Volunteer + {% endif %} + {% if registration_type == "donor" %} + Register As Mission Bit Donor + {% endif %} + {% csrf_token %} +
    + First Name: {{ user_form.first_name }} +
    +
    + Last Name: {{ user_form.last_name }} +
    +
    + Birthdate: {{ contact_form.birthdate }} +
    +
    + Email: {{ user_form.email }} +
    +
    + Choose Username: {{ user_form.username }} +
    +
    + Password: {{ user_form.password1 }} +
    +
    + Enter Same Password: {{ user_form.password2 }} +
    +
    + + {{ contact_form.race }}
    - {% endfor %} - {% endif %} - -

    Register with Mission Bit


    - Register As Student

    - - Register As Volunteer

    - - Register As Donor

    -
    - +
    + + {{ contact_form.which_best_describes_your_ethnicity }} +
    +
    + + {{ contact_form.gender }} +
    + +
    +
    +
    +
    {% endblock content %} diff --git a/home/templates/home/register_after_oauth.html b/home/templates/home/register_after_oauth.html index ba2b63a..a032d1a 100644 --- a/home/templates/home/register_after_oauth.html +++ b/home/templates/home/register_after_oauth.html @@ -1,29 +1,27 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} +{% load static %} - {% block content %} +{% block content %} -
    - -
    - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -

    Please Complete Registration

    -
    - {% csrf_token %} - Choose Your Role:

    - Student
    - Volunteer

    - +
    +
    + {% include "error.html" %} + + + Register As Student or Volunteer + {% csrf_token %} +
    + +
    +
    + +
    + +
    -
    +
    +
    {% endblock content %} diff --git a/home/templates/home/register_as_donor.html b/home/templates/home/register_as_donor.html deleted file mode 100644 index 98353c8..0000000 --- a/home/templates/home/register_as_donor.html +++ /dev/null @@ -1,27 +0,0 @@ -{% extends "home/home.html" %} -{% load crispy_forms_tags %} - -{% block content %} - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -

    Thank you for Registering As Mission Bit Donor

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    -
    -{% endblock content %} diff --git a/home/templates/home/register_as_student.html b/home/templates/home/register_as_student.html deleted file mode 100644 index 289301a..0000000 --- a/home/templates/home/register_as_student.html +++ /dev/null @@ -1,29 +0,0 @@ -{% extends "home/home.html" %} -{% load crispy_forms_tags %} - -{% block content %} - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -

    Register As Mission Bit Student

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    - -
    - -{% endblock content %} diff --git a/home/templates/home/register_as_volunteer.html b/home/templates/home/register_as_volunteer.html deleted file mode 100644 index 1223397..0000000 --- a/home/templates/home/register_as_volunteer.html +++ /dev/null @@ -1,30 +0,0 @@ -{% extends "home/home.html" %} -{% load crispy_forms_tags %} - -{% block content %} - - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -

    Register As Mission Bit Volunteer

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    - -
    - -{% endblock content %} diff --git a/home/templates/registration/login.html b/home/templates/registration/login.html index b7d9a40..92804fe 100644 --- a/home/templates/registration/login.html +++ b/home/templates/registration/login.html @@ -1,35 +1,22 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} {% load crispy_forms_tags %} {% block content %} - - - - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} - -

    Please Log In

    -
    - {% csrf_token %} - {{ form|crispy }} - -
    +
    +
    +
    +

    Please Log In

    + {% csrf_token %} +
    + Username: {{ form.username }} +
    +
    + Password: {{ form.password }} +
    + +
    +
    - - - - {% endblock content %} diff --git a/home/urls.py b/home/urls.py index 1de8a91..01eefbe 100644 --- a/home/urls.py +++ b/home/urls.py @@ -5,7 +5,6 @@ urlpatterns = [ path("", views.landing_page, name="home-landing_page"), path("logout/", views.logout_view, name="home-logout"), - path("register/", views.register, name="home-register"), path("home/", views.home, name="home-home"), path( "register_as_student/", diff --git a/home/views.py b/home/views.py index 5434daf..0cd85e9 100644 --- a/home/views.py +++ b/home/views.py @@ -1,11 +1,12 @@ -from django.shortcuts import render, redirect +from django.shortcuts import render, redirect, render_to_response from django.contrib.auth import logout from django.contrib.auth.models import Group from django.contrib.auth.models import User as DjangoUser from django.contrib.auth.decorators import login_required -from .forms import UserRegisterForm, ChangePwdForm +from .forms import UserRegisterForm, ContactRegisterForm, ChangePwdForm from django.contrib import messages from django.contrib.auth import update_session_auth_hash +from home.models.salesforce import Contact, User @login_required @@ -46,7 +47,7 @@ def change_pwd(request): request.user.userprofile.save() return redirect("home-home") else: - messages.error(request, "Please correct the error below.") + return render_to_response("home/change_pwd.html", {"form": form}) form = ChangePwdForm(request.user) return render(request, "home/change_pwd.html", {"form": form}) @@ -60,10 +61,6 @@ def login(request): return redirect("login") -def register(request): - return render(request, "home/register.html") - - def landing_page(request): return render(request, "home/landing_page.html") @@ -101,74 +98,135 @@ def register_after_oauth(request): def register_as_student(request): if request.method == "POST": - form = UserRegisterForm(request.POST) - if form.is_valid(): - new_user = DjangoUser.objects.create_user( - username=form.cleaned_data.get("username"), - email=form.cleaned_data.get("email"), - first_name=form.cleaned_data.get("first_name"), - last_name=form.cleaned_data.get("last_name"), - password=form.cleaned_data.get("password1"), - ) - student_group = Group.objects.get(name="student") - student_group.user_set.add(new_user) - first_name = form.cleaned_data.get("first_name") + user_form = UserRegisterForm(request.POST) + contact_form = ContactRegisterForm(request.POST) + if user_form.is_valid() and contact_form.is_valid(): + create_django_user(request, user_form, "student") + create_contact(request, user_form, contact_form, "Student") messages.success( request, - f"Student Account Successfully Created For {first_name}, please log in", + f"Student Account Successfully Created For {user_form.cleaned_data.get('first_name')}, please log in", ) return redirect("login") - return render(request, "home/register_as_student.html", {"form": form}) + else: + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "student", + }, + ) else: - form = UserRegisterForm() - return render(request, "home/register_as_student.html", {"form": form}) + user_form = UserRegisterForm() + contact_form = ContactRegisterForm() + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "student", + }, + ) def register_as_volunteer(request): if request.method == "POST": - form = UserRegisterForm(request.POST) - if form.is_valid(): - new_user = DjangoUser.objects.create_user( - username=form.cleaned_data.get("username"), - email=form.cleaned_data.get("email"), - first_name=form.cleaned_data.get("first_name"), - last_name=form.cleaned_data.get("last_name"), - password=form.cleaned_data.get("password1"), - ) - volunteer_group = Group.objects.get(name="volunteer") - volunteer_group.user_set.add(new_user) - first_name = form.cleaned_data.get("first_name") + user_form = UserRegisterForm(request.POST) + contact_form = ContactRegisterForm(request.POST) + if user_form.is_valid() and contact_form.is_valid(): + create_django_user(request, user_form, "volunteer") + create_contact(request, user_form, contact_form, "Volunteer") messages.success( request, - f"Volunteer Account Successfully Created For {first_name}, please log in", + f"Volunteer Account Successfully Created For {user_form.cleaned_data.get('first_name')}, please log in", ) return redirect("login") - return render(request, "home/register_as_volunteer.html", {"form": form}) + else: + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "volunteer", + }, + ) else: - form = UserRegisterForm() - return render(request, "home/register_as_volunteer.html", {"form": form}) + user_form = UserRegisterForm() + contact_form = ContactRegisterForm() + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "volunteer", + }, + ) def register_as_donor(request): if request.method == "POST": - form = UserRegisterForm(request.POST) - if form.is_valid(): - new_user = DjangoUser.objects.create_user( - username=form.cleaned_data.get("username"), - email=form.cleaned_data.get("email"), - first_name=form.cleaned_data.get("first_name"), - last_name=form.cleaned_data.get("last_name"), - password=form.cleaned_data.get("password1"), - ) - donor_group = Group.objects.get(name="donor") - donor_group.user_set.add(new_user) - first_name = form.cleaned_data.get("first_name") + user_form = UserRegisterForm(request.POST) + contact_form = ContactRegisterForm(request.POST) + if user_form.is_valid() and contact_form.is_valid(): + create_django_user(request, user_form, "donor") + create_contact(request, user_form, contact_form, "Donor") messages.success( request, - f"Donor Account Successfully Created For {first_name}, please log in", + f"Donor Account Successfully Created For {user_form.cleaned_data.get('first_name')}, please log in", ) return redirect("login") - return render(request, "home/register_as_donor.html", {"form": form}) + else: + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "donor", + }, + ) else: - form = UserRegisterForm() - return render(request, "home/register_as_donor.html", {"form": form}) + user_form = UserRegisterForm() + contact_form = ContactRegisterForm() + return render( + request, + "home/register.html", + { + "user_form": user_form, + "contact_form": contact_form, + "registration_type": "donor", + }, + ) + + +def create_django_user(request, form, group): + new_user = DjangoUser.objects.create_user( + username=form.cleaned_data.get("username"), + email=form.cleaned_data.get("email"), + first_name=form.cleaned_data.get("first_name"), + last_name=form.cleaned_data.get("last_name"), + password=form.cleaned_data.get("password1"), + ) + student_group = Group.objects.get(name=group) + student_group.user_set.add(new_user) + + +def create_contact(request, user_form, contact_form, title): + Contact.objects.create( + first_name=user_form.cleaned_data.get("first_name"), + last_name=user_form.cleaned_data.get("last_name"), + email=user_form.cleaned_data.get("email"), + birthdate=contact_form.cleaned_data.get("birthdate"), + title=title, + owner=User.objects.filter(is_active=True).first(), + race=contact_form.cleaned_data.get("race"), + which_best_describes_your_ethnicity=contact_form.cleaned_data.get( + "which_best_describes_your_ethnicity" + ), + gender=contact_form.cleaned_data.get("gender"), + ) diff --git a/html/announcements.html b/html/announcements.html new file mode 100644 index 0000000..c13f3a0 --- /dev/null +++ b/html/announcements.html @@ -0,0 +1,21 @@ +
    +
    +

    Announcements


    + {% for announcement in announcements reversed %} +
    +

    {{ announcement.announcement.title }}


    +

    {{ announcement.announcement.announcement }}


    +

    {{ announcement.announcement.created_by }} on {{ announcement.announcement.posted.date }}


    +
    +
    + {% csrf_token %} +

    + +

    + + +
    +

    + {% endfor %} +
    +
    diff --git a/html/base.html b/html/base.html new file mode 100644 index 0000000..59793d9 --- /dev/null +++ b/html/base.html @@ -0,0 +1,41 @@ + +{% load static %} + + + + + + + + + + + + + + Mission Bit + {% include 'manipulation_js.html' %} + + + + + {% include 'header.html' %} + + {% include 'instafeed.html' %} + + {% include 'left_side_panel.html' %} + +
    +
    +
    +
    + {% block content %} + + {% endblock %} +
    +
    + + {% include 'footer.html' %} + + + diff --git a/html/error.html b/html/error.html new file mode 100644 index 0000000..1631fee --- /dev/null +++ b/html/error.html @@ -0,0 +1,15 @@ +{% load static %} + +
    + {% if form.errors %} + {% for field in form %} + {% for error in field.errors %} +
    +

    {{ error|escape }} + +

    +
    + {% endfor %} + {% endfor %} + {% endif %} +
    diff --git a/html/footer.html b/html/footer.html new file mode 100644 index 0000000..06f94bc --- /dev/null +++ b/html/footer.html @@ -0,0 +1,13 @@ +
    +
    + +
    +
    +
    +
    +
    +
    + + +
    ALL Rights Reserved.
    +
    diff --git a/html/forms.html b/html/forms.html new file mode 100644 index 0000000..19dd6fd --- /dev/null +++ b/html/forms.html @@ -0,0 +1,18 @@ +
    +
    +

    Forms


    + {% for form in forms reversed %} +
    +

    {{ form.form.name }}


    +

    {{ form.form.description }}


    +

    {{ form.form.created_by }} on {{ form.form.posted.date }}



    + {% if form.form.esign %} +

    Esign Here


    + {% endif %} +

    + Download Form +

    +

    + {% endfor %} +
    +
    diff --git a/html/header.html b/html/header.html new file mode 100644 index 0000000..4e7489d --- /dev/null +++ b/html/header.html @@ -0,0 +1,21 @@ +
    + diff --git a/html/home_base.html b/html/home_base.html new file mode 100644 index 0000000..906c84d --- /dev/null +++ b/html/home_base.html @@ -0,0 +1,59 @@ + +{% load static %} + + + + + + + + + + + + + + + + + Mission Bit + + {% include "manipulation_js.html" %} + + + + {% include "header.html" %} + + {% include "instafeed.html" %} + +
    +
    +
    +
    + {% block content %} + + {% endblock %} +
    +
    + + + + + {% include "footer.html" %} + + + diff --git a/html/instafeed.html b/html/instafeed.html new file mode 100644 index 0000000..651d198 --- /dev/null +++ b/html/instafeed.html @@ -0,0 +1,32 @@ + +
    +

    Instagram Feed


    +
    + +
    +
    + +
    + + +
    +
    + + diff --git a/html/left_side_panel.html b/html/left_side_panel.html new file mode 100644 index 0000000..ac9ffc5 --- /dev/null +++ b/html/left_side_panel.html @@ -0,0 +1,87 @@ +{% load static %} + +
    +
    +
    +
    +
    + +
    +
    +
    + Home +
    + {% if "staff" in user_groups %} +
    + Courses + +
    +
    + Users + +
    +
    + Forms + +
    +
    + Communication + +
    +
    + Attendance +
    + {% endif %} + {% if "teacher" in user_groups %} +
    + My Class +
    + {% if classroom.forum %} +
    + {{ classroom.forum_title }} +
    + {% endif %} +
    + Attendance +
    + {% endif %} + {% if "student" in user_groups %} +
    + My Class +
    + {% if classroom.forum %} +
    + {{ classroom.forum_title }} +
    + {% endif %} +
    + Attendance +
    + {% endif %} +
    +
    diff --git a/html/manipulation_js.html b/html/manipulation_js.html new file mode 100644 index 0000000..bce01bc --- /dev/null +++ b/html/manipulation_js.html @@ -0,0 +1,100 @@ +{% load settings_tags %} + + + + + + diff --git a/html/message.html b/html/message.html new file mode 100644 index 0000000..07efd16 --- /dev/null +++ b/html/message.html @@ -0,0 +1,15 @@ +{% load static %} + +{% if messages %} +
    +
    + {% for message in messages %} +
    +

    {{ message }} + +

    +
    + {% endfor %} +
    +
    +{% endif %} diff --git a/html/notifications.html b/html/notifications.html new file mode 100644 index 0000000..f9a63fb --- /dev/null +++ b/html/notifications.html @@ -0,0 +1,24 @@ +
    +
    +

    Notifications


    + {% for notification in notifications %} +
    +

    {{ notification.subject }}


    +
    +

    {{ notification.notification }}


    +

    Mission Bit on {{ notification.notified.date }}


    +

    +

    + {% csrf_token %} + + +

    + +

    +
    +

    +
    +
    + {% endfor %} +
    +
    diff --git a/html/registration_error.html b/html/registration_error.html new file mode 100644 index 0000000..bedca5f --- /dev/null +++ b/html/registration_error.html @@ -0,0 +1,24 @@ +{% load static %} + +
    +{% if user_form.errors or contact_form.errors %} + {% for field in user_form %} + {% for error in field.errors %} +
    +

    {{ error|escape }} + +

    +
    + {% endfor %} + {% endfor %} + {% for field in contact_form %} + {% for error in field.errors %} +
    +

    {{ error|escape }} + +

    +


    + {% endfor %} + {% endfor %} +{% endif %} +
    diff --git a/missionbit/azure_storage_backend.py b/missionbit/azure_storage_backend.py index 9cecacd..e18a793 100644 --- a/missionbit/azure_storage_backend.py +++ b/missionbit/azure_storage_backend.py @@ -3,10 +3,11 @@ from storages.backends.azure_storage import AzureStorage from storages.utils import setting + @deconstructible class CustomAzureStorage(AzureStorage): # This is a workaround for AzureStorage to support custom domains - custom_domain = setting('AZURE_CUSTOM_DOMAIN', None) + custom_domain = setting("AZURE_CUSTOM_DOMAIN", None) @property def service(self): @@ -15,11 +16,12 @@ def service(self): self.account_name, self.account_key, is_emulated=self.is_emulated, - custom_domain=self.custom_domain) + custom_domain=self.custom_domain, + ) return self._service def url(self, name, expire=None): url = super().url(name, expire=expire) - if self.is_emulated and url.startswith('https://azurite:'): - url = url.replace('https://azurite:', 'http://localhost:') + if self.is_emulated and url.startswith("https://azurite:"): + url = url.replace("https://azurite:", "http://localhost:") return url diff --git a/missionbit/settings.py b/missionbit/settings.py index 5155e94..23cfe49 100644 --- a/missionbit/settings.py +++ b/missionbit/settings.py @@ -19,6 +19,14 @@ # Build paths inside the project like this: os.path.join(BASE_DIR, ...) BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) +# Static files (CSS, JavaScript, Images) +# https://docs.djangoproject.com/en/1.9/howto/static-files/ +STATIC_ROOT = os.path.join(BASE_DIR, "staticfiles") +STATIC_URL = "/static/" + + +STATICFILES_DIRS = (os.path.join(BASE_DIR, "static"),) + # Quick-start development settings - unsuitable for production # See https://docs.djangoproject.com/en/2.2/howto/deployment/checklist/ @@ -53,7 +61,8 @@ "coverage", # <- for testing "salesforce", # <- salesforce database "django_q", # <- For queueing tasks - "storages", # <- Storing uploaded files in Azure Storage + "storages", # <- Storing uploaded files in Azure Storage + "static", # <- Accessing Static HTML templates ] MIDDLEWARE = [ @@ -64,6 +73,7 @@ "django.contrib.auth.middleware.AuthenticationMiddleware", "django.contrib.messages.middleware.MessageMiddleware", "django.middleware.clickjacking.XFrameOptionsMiddleware", + "whitenoise.middleware.WhiteNoiseMiddleware", # <- Whitenoise for serving static assets ] ROOT_URLCONF = "missionbit.urls" @@ -71,7 +81,10 @@ TEMPLATES = [ { "BACKEND": "django.template.backends.django.DjangoTemplates", - "DIRS": [], + "DIRS": [ + os.path.join(BASE_DIR, "static/html"), + os.path.join(BASE_DIR, "html/"), + ], "APP_DIRS": True, "OPTIONS": { "context_processors": [ @@ -81,6 +94,8 @@ "django.contrib.messages.context_processors.messages", "social_django.context_processors.backends", # <- Social Django Oauth Google "social_django.context_processors.login_redirect", # <- Social Django Oauth Google + "context_processors.user_groups", + "context_processors.user_classroom", ] }, } @@ -184,11 +199,6 @@ EMAIL_HOST_USER = os.getenv("EMAIL_HOST_USER") EMAIL_HOST_PASSWORD = os.getenv("EMAIL_HOST_PASSWORD") -# Static files (CSS, JavaScript, Images) -# https://docs.djangoproject.com/en/2.2/howto/static-files/ - -STATIC_URL = "/static/" - LOGIN_URL = "home-landing_page" LOGIN_REDIRECT_URL = "home-home" @@ -196,11 +206,37 @@ CRISPY_TEMPLATE_PACK = "bootstrap4" # Azure file storage -DEFAULT_FILE_STORAGE = 'missionbit.azure_storage_backend.CustomAzureStorage' -AZURE_EMULATED_MODE = os.getenv('AZURE_EMULATED_MODE') == 'true' -AZURE_ACCOUNT_NAME = os.getenv('AZURE_ACCOUNT_NAME') -AZURE_ACCOUNT_KEY = os.getenv('AZURE_ACCOUNT_KEY') -AZURE_CONTAINER = os.getenv('AZURE_CONTAINER') -AZURE_CUSTOM_DOMAIN = os.getenv('AZURE_CUSTOM_DOMAIN', f'{AZURE_ACCOUNT_NAME}.blob.core.windows.net') -AZURE_PROTOCOL = 'http' if AZURE_EMULATED_MODE else 'https' -MEDIA_URL = os.getenv('MEDIA_URL', f'{AZURE_PROTOCOL}://{AZURE_CUSTOM_DOMAIN}/{AZURE_CONTAINER}/') +DEFAULT_FILE_STORAGE = "missionbit.azure_storage_backend.CustomAzureStorage" +AZURE_EMULATED_MODE = os.getenv("AZURE_EMULATED_MODE") == "true" +AZURE_ACCOUNT_NAME = os.getenv("AZURE_ACCOUNT_NAME") +AZURE_ACCOUNT_KEY = os.getenv("AZURE_ACCOUNT_KEY") +AZURE_CONTAINER = os.getenv("AZURE_CONTAINER") +AZURE_CUSTOM_DOMAIN = os.getenv( + "AZURE_CUSTOM_DOMAIN", f"{AZURE_ACCOUNT_NAME}.blob.core.windows.net" +) +AZURE_PROTOCOL = "http" if AZURE_EMULATED_MODE else "https" +MEDIA_URL = os.getenv( + "MEDIA_URL", f"{AZURE_PROTOCOL}://{AZURE_CUSTOM_DOMAIN}/{AZURE_CONTAINER}/" +) + +INSTAUSERID = os.getenv("INSTAUSERID") +INSTATOKEN = os.getenv("INSTATOKEN") + +""" +LOGGING = { + 'version': 1, + 'disable_existing_loggers': False, + 'handlers': { + 'console': { + 'level': 'DEBUG', + 'class': 'logging.StreamHandler', + } + }, + 'loggers': { + 'django.db.backends': { + 'handlers': ['console'], + 'level': 'DEBUG', + }, + } +} +""" diff --git a/missionbit/urls.py b/missionbit/urls.py index 0e3e010..aaefad1 100644 --- a/missionbit/urls.py +++ b/missionbit/urls.py @@ -26,5 +26,5 @@ path("volunteer/", include("volunteer.urls")), path("donor/", include("donor.urls")), path("attendance/", include("attendance.urls")), - url(r"^auth/", include("social_django.urls", namespace="social")) + url(r"^auth/", include("social_django.urls", namespace="social")), ] diff --git a/requirements.txt b/requirements.txt index fec3104..692d863 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,3 +26,4 @@ unittest-xml-reporting==2.5.1 django-q==1.0.1 django-storages[azure]==1.7.1 Werkzeug==0.15.5 +whitenoise==4.1.3 diff --git a/staff/staff_views_helper.py b/staff/staff_views_helper.py index ad82eca..b24216e 100644 --- a/staff/staff_views_helper.py +++ b/staff/staff_views_helper.py @@ -1,19 +1,36 @@ from django.contrib.auth.models import User as DjangoUser from django.contrib.auth.models import Group +from django.shortcuts import render from home.models.salesforce import ClassEnrollment, Contact, ClassOffering -from home.models.models import Announcement, UserProfile, Classroom, ClassroomMembership, Attendance, Session, FormDistribution, Form, AnnouncementDistribution +from home.models.models import ( + Announcement, + UserProfile, + Classroom, + ClassroomMembership, + Attendance, + Session, + FormDistribution, + Form, + AnnouncementDistribution, +) +from social_django.models import UserSocialAuth from django.core.mail import send_mail, EmailMultiAlternatives from django.template.loader import render_to_string from django.utils.html import strip_tags from django.conf import settings from django.contrib import messages from datetime import timedelta, datetime +from salesforce.dbapi.exceptions import * +import random def create_user_with_profile(form, random_password): + username = validate_username( + "%s.%s" + % (form.cleaned_data.get("first_name"), form.cleaned_data.get("last_name")) + ) new_user = DjangoUser.objects.create_user( - username="%s.%s" - % (form.cleaned_data.get("first_name"), form.cleaned_data.get("last_name")), + username=username, email=form.cleaned_data.get("email"), first_name=form.cleaned_data.get("first_name"), last_name=form.cleaned_data.get("last_name"), @@ -24,8 +41,18 @@ def create_user_with_profile(form, random_password): return new_user +def validate_username(username): + res_username = username + while DjangoUser.objects.filter(username=res_username).exists(): + random_number = random.randint(1, 10000) + res_username = username + str(random_number) + return res_username + + def parse_new_user(new_user, form): birthdate = form.cleaned_data.get("birthdate") + if birthdate is None: + birthdate = datetime(1901, 1, 1) new_user.userprofile.change_pwd = True new_user.userprofile.salesforce_id = "%s%s%s%s%s" % ( form.cleaned_data.get("first_name")[:3].lower(), @@ -38,6 +65,32 @@ def parse_new_user(new_user, form): return new_user +def save_user_to_salesforce(request, form): + try: + form.save() + except SalesforceError: + messages.error(request, "Error Saving User To Salesforce Database.") + return render(request, "create_staff_user.html", {"form": form}) + + +def create_mission_bit_user(request, form, group): + random_password = DjangoUser.objects.make_random_password() + new_user = create_user_with_profile(form, random_password) + email = form.cleaned_data.get("email") + student_group = Group.objects.get(name=group) + student_group.user_set.add(new_user) + UserSocialAuth.objects.create( + uid=form.cleaned_data.get("email"), + user_id=new_user.userprofile.user_id, + provider="google-oauth2", + ) + first_name = form.cleaned_data.get("first_name") + messages.success(request, f"Student Account Successfully Created For {first_name}") + email_new_user( + request, email, first_name, group, new_user.username, random_password + ) + + def enroll_in_class(form, contact): ClassEnrollment.objects.get_or_create( name=form.cleaned_data.get("course"), @@ -51,7 +104,9 @@ def enroll_in_class(form, contact): def setup_classroom(request, form): email_list = [] teacher = get_django_user_from_contact(form.cleaned_data.get("teacher")) - teacher_assistant = get_django_user_from_contact(form.cleaned_data.get("teacher_assistant")) + teacher_assistant = get_django_user_from_contact( + form.cleaned_data.get("teacher_assistant") + ) email_list.append(teacher.email) email_list.append(teacher_assistant.email) classroom = Classroom.objects.create(course=form.cleaned_data.get("course").name) @@ -74,20 +129,20 @@ def setup_classroom(request, form): def get_django_user_from_contact(contact): - return DjangoUser.objects.get(id=UserProfile.objects.get(salesforce_id=contact.client_id.lower()).user_id) + return DjangoUser.objects.get( + id=UserProfile.objects.get(salesforce_id=contact.client_id.lower()).user_id + ) def retrieve_userprofile_from_form(form, name_string): return UserProfile.objects.get( - salesforce_id=form.cleaned_data.get(name_string).client_id.lower() - ) + salesforce_id=form.cleaned_data.get(name_string).client_id.lower() + ) def create_classroom_membership(django_user_member, classroom, membership_type): cm = ClassroomMembership( - member=django_user_member, - classroom=classroom, - membership_type=membership_type + member=django_user_member, classroom=classroom, membership_type=membership_type ) cm.save() @@ -99,18 +154,19 @@ def generate_classroom_sessions_and_attendance(classroom): classroom.save() class_offering = ClassOffering.objects.get(name=classroom.course) dates = class_offering_meeting_dates(class_offering) - sessions = [Session( - classroom_id=classroom.id, - date=day - ) for day in dates] + sessions = [Session(classroom_id=classroom.id, date=day) for day in dates] Session.objects.bulk_create(sessions) classroom_students = get_users_of_type_from_classroom(classroom, "student") - attendances = [Attendance( + attendances = [ + Attendance( student_id=student.id, - session_id=sessions[x].id, + session_id=session.id, classroom_id=classroom.id, - date=day, - ) for student in classroom_students for x, day in enumerate(dates)] + date=session.date, + ) + for student in classroom_students + for session in sessions + ] Attendance.objects.bulk_create(attendances) @@ -119,20 +175,28 @@ def get_classroom_sessions(classroom): def get_users_of_type_from_classroom(classroom, type): - return DjangoUser.objects.filter(classroom=classroom, classroom_member__membership_type=type) # Handle Empty Set Case + return DjangoUser.objects.filter( + classroom=classroom, classroom_member__membership_type=type + ) # Handle Empty Set Case def get_teacher_from_classroom(classroom): - return DjangoUser.objects.get(classroom=classroom, classroom_member__membership_type="teacher") # Handle a multiple values returned exception + return DjangoUser.objects.get( + classroom=classroom, classroom_member__membership_type="teacher" + ) # Handle a multiple values returned exception def get_teacher_assistant_from_classroom(classroom): - return DjangoUser.objects.get(classroom=classroom, classroom_member__membership_type="teacher_assistant") # Handle a multiple values returned exception + return DjangoUser.objects.get( + classroom=classroom, classroom_member__membership_type="teacher_assistant" + ) # Handle a multiple values returned exception def get_classroom_by_django_user(django_user): try: return Classroom.objects.get(membership_classroom__member=django_user) + except TypeError: + return None except Classroom.DoesNotExist: return None @@ -181,23 +245,25 @@ def email_classroom(request, email_list, classroom_name): def get_users_from_form(form): - group_users = DjangoUser.objects.filter(groups__name__in=[group.name for group in form.cleaned_data.get("recipient_groups")]) - classroom_users = DjangoUser.objects.filter(classroom__in=[classroom for classroom in form.cleaned_data.get("recipient_classrooms")]) + group_users = DjangoUser.objects.filter( + groups__name__in=list(form.cleaned_data.get("recipient_groups")) + ) + classroom_users = DjangoUser.objects.filter( + classroom__in=list(form.cleaned_data.get("recipient_classrooms")) + ) return (classroom_users | group_users).distinct() def get_emails_from_form_distributions(form_distributions): - return DjangoUser.objects.filter(email__in=[form_dist.user.email for form_dist in form_distributions]) + return DjangoUser.objects.filter( + email__in=[form_dist.user.email for form_dist in form_distributions] + ) def email_announcement(request, subject, message, email_list): msg_html = render_to_string( "email_templates/announcement_email.html", - { - "subject": subject, - "message": message, - "from": request.user, - }, + {"subject": subject, "message": message, "from": request.user}, ) from_user = settings.EMAIL_HOST_USER recipient_list = [ @@ -215,11 +281,12 @@ def email_announcement(request, subject, message, email_list): def bulk_distribute_announcement(user_list, announcement): - announcement_distributions = [AnnouncementDistribution( - user_id=user.id, - announcement_id=announcement.id, - dismissed=False - ) for user in user_list] + announcement_distributions = [ + AnnouncementDistribution( + user_id=user.id, announcement_id=announcement.id, dismissed=False + ) + for user in user_list + ] AnnouncementDistribution.objects.bulk_create(announcement_distributions) @@ -230,7 +297,7 @@ def email_posted_form(request, esign, subject, message, email_list): "subject": subject, "message": message, "from": DjangoUser.objects.get(id=request.user.id), - "esign_link": esign + "esign_link": esign, }, ) text_content = "Please view your new form (attached)" @@ -249,12 +316,16 @@ def email_posted_form(request, esign, subject, message, email_list): messages.add_message(request, messages.SUCCESS, "Recipients Successfully Emailed") -def change_classroom_lead(former_leader_user_id, new_leader_user_id, course_id, leader_type): +def change_classroom_lead( + former_leader_user_id, new_leader_user_id, course_id, leader_type +): class_offering = get_class_offering_by_id(course_id) new_lead_contact = get_contact_by_user_id(new_leader_user_id) classroom = Classroom.objects.get(id=course_id) remove_user_from_classroom(former_leader_user_id, course_id) - create_classroom_membership(DjangoUser.objects.get(id=new_leader_user_id), classroom, leader_type) + create_classroom_membership( + DjangoUser.objects.get(id=new_leader_user_id), classroom, leader_type + ) ClassEnrollment.objects.get_or_create( created_by=class_offering.created_by, contact=new_lead_contact, @@ -267,8 +338,12 @@ def change_classroom_lead(former_leader_user_id, new_leader_user_id, course_id, def remove_user_from_classroom(user_id, course_id): - remove_enrollment(get_contact_by_user_id(user_id), get_class_offering_by_id(course_id)) - ClassroomMembership.objects.get(classroom=Classroom.objects.get(id=course_id), member_id=user_id).delete() + remove_enrollment( + get_contact_by_user_id(user_id), get_class_offering_by_id(course_id) + ) + ClassroomMembership.objects.get( + classroom=Classroom.objects.get(id=course_id), member_id=user_id + ).delete() def add_user_to_classroom(user_id, course_id, member_type): @@ -276,13 +351,13 @@ def add_user_to_classroom(user_id, course_id, member_type): ClassroomMembership.objects.create( classroom=Classroom.objects.get(id=course_id), member=DjangoUser.objects.get(id=user_id), - membership_type=member_type + membership_type=member_type, ) ClassEnrollment.objects.create( created_by=class_offering.created_by, contact=get_contact_by_user_id(user_id), status="Enrolled", - class_offering=class_offering + class_offering=class_offering, ) @@ -336,27 +411,21 @@ def distribute_forms(request, posted_form, user_list): def bulk_create_form_distributions(form, users): - form_dists = [FormDistribution( - form=form, - user=user, - submitted=False - )for user in users] + form_dists = [ + FormDistribution(form=form, user=user, submitted=False) for user in users + ] FormDistribution.objects.bulk_create(form_dists) def create_form_distribution(posted_form, user): - dist = FormDistribution( - form=posted_form, - user=user, - submitted=False - ) + dist = FormDistribution(form=posted_form, user=user, submitted=False) dist.save() def get_outstanding_forms(): outstanding_form_dict = {} for form in Form.objects.all(): - distributions = FormDistribution.objects.filter(form__in=form) + distributions = form.form_to_be_signed.all() outstanding_form_dict.update({form.name: distributions}) return outstanding_form_dict @@ -386,7 +455,9 @@ def email_form_notification(request, form, email_list): def mark_announcement_dismissed(announcement, user): - announcement = AnnouncementDistribution.objects.get(announcement_id=announcement.id, user_id=user.id) + announcement = AnnouncementDistribution.objects.get( + announcement_id=announcement.id, user_id=user.id + ) announcement.dismissed = True announcement.save() @@ -400,23 +471,31 @@ def update_session(request, form): session = Session.objects.get(id=request.POST.get("session_id")) if request.POST.get("change_title"): session.title = form.cleaned_data.get("title") + messages.add_message(request, messages.SUCCESS, "Session Title Updated") if request.POST.get("change_description"): session.description = form.cleaned_data.get("description") + messages.add_message(request, messages.SUCCESS, "Session Description Updated") if request.POST.get("change_lesson_plan"): - session.lesson_plan = form.cleaned_data.get("lesson_plan") + session.lesson_plan = str(form.cleaned_data.get("lesson_plan")) + messages.add_message(request, messages.SUCCESS, "Session Lesson Plan Updated") if request.POST.get("change_activity"): - session.activity = form.cleaned_data.get("activity") + session.activity = str(form.cleaned_data.get("activity")) + messages.add_message(request, messages.SUCCESS, "Session Activity Updated") if request.POST.get("change_lecture"): - session.lecture = form.cleaned_data.get("lecture") + session.lecture = str(form.cleaned_data.get("lecture")) + messages.add_message(request, messages.SUCCESS, "Session Lecture Updated") if request.POST.get("change_video"): - session.video = form.cleaned_data.get("video") + session.video = str(form.cleaned_data.get("video")) + messages.add_message(request, messages.SUCCESS, "Session Video Updated") session.save() def get_class_member_dict(classroom): teacher = get_users_of_type_from_classroom(classroom, "teacher").first() teacher_id = teacher.id - teacher_assistant = get_users_of_type_from_classroom(classroom, "teacher_assistant").first() + teacher_assistant = get_users_of_type_from_classroom( + classroom, "teacher_assistant" + ).first() teacher_assistant_id = teacher_assistant.id return { "teacher": teacher, @@ -424,7 +503,7 @@ def get_class_member_dict(classroom): "teacher_assistant": teacher_assistant, "teacher_assistant_id": teacher_assistant_id, "volunteers": get_users_of_type_from_classroom(classroom, "volunteer"), - "students": get_users_of_type_from_classroom(classroom, "student") + "students": get_users_of_type_from_classroom(classroom, "student"), } @@ -438,14 +517,25 @@ def get_course_attendance_statistic(course_id): def get_my_announcements(request, group): - classroom = get_classroom_by_django_user(request.user) - announcements = (Announcement.objects.filter(recipient_groups=Group.objects.get(name=group)) | Announcement.objects.filter(recipient_classrooms=classroom)).distinct() - announcement_distributions = AnnouncementDistribution.objects.filter(announcement__in=announcements, user_id=request.user.id, dismissed=False) - return announcement_distributions + return AnnouncementDistribution.objects.filter( + announcement__in=( + Announcement.objects.filter( + recipient_groups__in=Group.objects.filter(name=group) + ) + | Announcement.objects.filter( + recipient_classrooms__in=[get_classroom_by_django_user(request.user)] + ) + ), + dismissed=False, + ) def get_my_forms(request, group): - classroom = get_classroom_by_django_user(request.user) - forms = (Form.objects.filter(recipient_groups=Group.objects.get(name=group)) | Form.objects.filter(recipient_classrooms=classroom)).distinct() - form_distributions = FormDistribution.objects.filter(form__in=forms, user_id=request.user.id, submitted=False) - return form_distributions + return FormDistribution.objects.filter( + form__in=Form.objects.filter( + recipient_groups__in=Group.objects.filter(name=group) + ) + | Form.objects.filter( + recipient_classrooms__in=[get_classroom_by_django_user(request.user)] + ) + ) diff --git a/staff/templates/add_forum.html b/staff/templates/add_forum.html index d0a7bfb..55af9c8 100644 --- a/staff/templates/add_forum.html +++ b/staff/templates/add_forum.html @@ -1,20 +1,29 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} +{% load static %} {% block content %} - +
    +
    + + {% include "error.html" %} -

    Add Forum to Classroom - {{ classroom.course }}

    -
    + {% csrf_token %} - {{ form|crispy }} +
    + {{ form.forum_title }} + +
    +
    + {{ form.forum }} + +

    - +
    +
    + {% endblock content %} diff --git a/staff/templates/classroom_detail.html b/staff/templates/classroom_detail.html index b613087..642ef8a 100644 --- a/staff/templates/classroom_detail.html +++ b/staff/templates/classroom_detail.html @@ -1,187 +1,132 @@ -{% extends 'staff_base.html' %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} - - - - - - - - -
    -

    {{ classroom.course }} - {{ class_members|get_item:"teacher"}}


    -

    Current Attendance: {{ classroom.attendance_summary.attendance_statistic }}%

    -
    - -

    +
    +
    + {% include "error.html" %} +

    {{ classroom.course }}


    +

    {{ class_members|get_item:"teacher"}}

    +

    {{ class_members|get_item:"teacher_assistant"}}


    + + +

    Current Attendance: {{ classroom.attendance_summary.attendance_statistic }}%    +

    +
    +
    +

    Curriculum     + +


    -

    Curriculum

    -
    - -

    -

    +
    {% if classroom.forum_title %} -

    Current Forum: {{ classroom.forum_title }}

    +

    Current Forum: {{ classroom.forum_title }}   

    {% else %} -

    No Forum

    +

    No Forum   

    {% endif %} - -


    -

    + +
    +
    - - - - - - - - - - {% csrf_token %} - - - - - - - - - - - - {% csrf_token %} - - - - - - - - - - {% for volunteer in class_members|get_item:"volunteers" %} - - - {% csrf_token %} - - - - - - - - - - {% endfor %} - {% for student in class_members|get_item:"students" %} +
    +
    +
    RoleClass MemberAlterSubmit
    Teacher{{ class_members|get_item:"teacher" }}{{ change_teacher_form|crispy }}
    Teacher Assistant{{ class_members|get_item:"teacher_assistant" }}{{ change_teacher_form|crispy }}
    Volunteer{{ volunteer }}Can't Swap Volunteer
    + - - {% csrf_token %} - - - - - - - - - - {% endfor %} -
    Student{{ student }}Can't Swap Student
    - + Role + Class Member + Alter + + + + +
    + {% csrf_token %} + Teacher + {{ class_members|get_item:"teacher" }} + +
    + {{ change_teacher_form.teacher }} +
    + + + + + +
    + + +
    + {% csrf_token %} + Teacher Assistant + {{ class_members|get_item:"teacher_assistant" }} + +
    + {{ change_teacher_form.teacher }} +
    + + + + + +
    + + {% for volunteer in class_members|get_item:"volunteers" %} + +
    + {% csrf_token %} + Volunteer + {{ volunteer }} + Can't Swap Volunteer + + + + +
    + + {% endfor %} + {% for student in class_members|get_item:"students" %} + +
    + {% csrf_token %} + Student + {{ student }} + Can't Swap Student + + + + +
    + + {% endfor %} +
    {% csrf_token %} -
    {% endblock content %} diff --git a/staff/templates/classroom_management.html b/staff/templates/classroom_management.html index be6ed3b..de9b627 100644 --- a/staff/templates/classroom_management.html +++ b/staff/templates/classroom_management.html @@ -1,75 +1,22 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% block content %} - +{% include "message.html" %} - - - - -
    {% if classrooms %} {% for classroom in classrooms %} -
    +
    +

    {{ classroom }}

    {{ class_dicts|get_item:classroom.course|get_item:"teacher" }}
    {{ class_dicts|get_item:classroom.course|get_item:"teacher_assistant" }}
    -
    - - -
    + Go +

    {% endfor %} {% endif %} -
    {% endblock content %} diff --git a/staff/templates/communication_manager.html b/staff/templates/communication_manager.html index fd9e6e9..f6023be 100644 --- a/staff/templates/communication_manager.html +++ b/staff/templates/communication_manager.html @@ -1,118 +1,98 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% block content %} - - - - -
    -

    Communication Manager


    +

    Communication Manager


    {% if announcements %} -

    Announcements


    - - - - - - - - {% for announcement in announcements %} - - - - - - - {% endfor %} -
    TitleAnnouncementCreated By - DateDelete
    {{ announcement.title }}

    {{ announcement.announcement }}

    {{ announcement.created_by }} - {{ announcement.posted }}

    -
    - {% csrf_token %} - - - -
    -
    +
    +
    +

    Announcements


    + + + + + + + + {% for announcement in announcements %} + + + + + + + {% endfor %} +
    TitleAnnouncementCreated By - DateDelete
    {{ announcement.title }}

    {{ announcement.announcement }}

    {{ announcement.created_by }} - {{ announcement.posted.date }}

    +
    + {% csrf_token %} + + + +
    +
    +
    +
    {% endif %} {% if notifications %} -

    Notifications


    - - - - - - - - {% for notification in notifications %} - - - - - - - {% endfor %} -
    SubjectNotificationNotified User - DateDelete
    {{ notification.subject }}

    {{ notification.notification }}

    {{ notification.user }} - {{ notification.notified }}

    -
    - {% csrf_token %} - - - -
    -
    +
    +
    +

    Notifications


    + + + + + + + + {% for notification in notifications %} + + + + + + + {% endfor %} +
    SubjectNotificationNotified User - DateDelete
    {{ notification.subject }}

    {{ notification.notification }}

    {{ notification.user }} - {{ notification.notified.date }}

    +
    + {% csrf_token %} + + + +
    +
    +
    +
    {% endif %} {% if forms %} -

    Forms


    - - - - - - - - {% for form in forms %} - - - - - - - {% endfor %} -
    NamedescriptionCreated By - DateDelete
    {{ form.name }}

    {{ form.description }}

    {{ form.created_by }} - {{ form.posted }}

    -
    - {% csrf_token %} - - - -
    -
    +
    +
    +

    Forms


    + + + + + + + + {% for form in forms %} + + + + + + + {% endfor %} +
    NameDescriptionCreated By - DateDelete
    {{ form.name }}

    {{ form.description }}

    {{ form.created_by }} - {{ form.posted.date }}

    +
    + {% csrf_token %} + + + +
    +
    +
    +
    {% endif %}
    {% endblock content %} diff --git a/staff/templates/create_class_offering.html b/staff/templates/create_class_offering.html index 57d8fab..d6c970c 100644 --- a/staff/templates/create_class_offering.html +++ b/staff/templates/create_class_offering.html @@ -1,19 +1,49 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} -
    - -
    - -
    -

    Create Class Offering

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - +
    +
    + {% include "error.html" %} + + {% csrf_token %} + Create Class Offering +
    + {{ form.name}} + +
    +
    + {{ form.description}} + +
    +
    + + {{ form.instructor }} +
    +
    + + {{ form.start_date }} +
    +
    + + {{ form.end_date }} +
    +
    + + {{ form.location }} +
    +
    + + {{ form.meeting_days }} +
    +
    + + {{ form.created_by }} +
    +
    +
    +
    + {% endblock content %} diff --git a/staff/templates/create_classroom.html b/staff/templates/create_classroom.html index 154e61a..acf80bf 100644 --- a/staff/templates/create_classroom.html +++ b/staff/templates/create_classroom.html @@ -1,21 +1,45 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} -
    - -
    - -
    -

    Create Classroom

    - -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    -
    +
    +
    + {% include "error.html" %} +
    + Create Classroom + {% csrf_token %} +
    + + {{ form.course }} +
    +
    + + {{ form.teacher }} +
    +
    + + {{ form.teacher_assistant }} +

    +
    + + {{ form.created_by }} +

    +
    +
    +
    + + {{ form.volunteers }} +

    +
    + + {{ form.students }} +

    +
    +
    + +

    +
    +
    {% endblock content %} diff --git a/staff/templates/create_esign.html b/staff/templates/create_esign.html index eae01f3..5537c7e 100644 --- a/staff/templates/create_esign.html +++ b/staff/templates/create_esign.html @@ -1,19 +1,24 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} +{% load static %} {% block content %} - - - -
    -

    Create e-sign form

    -
    - {% csrf_token %} - {{ form|crispy }} +
    +
    + {% include "error.html" %} + + Create E-Sign Link
    + {% csrf_token %} +
    + {{ form.name }} + +
    +
    + {{ form.link }} + +

    - - + +
    +
    {% endblock content %} diff --git a/staff/templates/create_staff_user.html b/staff/templates/create_staff_user.html index a983f65..34fad58 100644 --- a/staff/templates/create_staff_user.html +++ b/staff/templates/create_staff_user.html @@ -1,21 +1,44 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} - -
    - -
    - -
    -

    Create Staff User

    -
    +
    +
    + {% include "error.html" %} + + Create Staff User {% csrf_token %} - {{ form|crispy }} -
    - +
    + + {{ form.first_name }} +
    +
    + + {{ form.last_name }} +
    +
    + + {{ form.email }} +
    +
    + + {{ form.birthdate }} +
    +
    + + {{ form.title }} +
    +
    + + {{ form.account }} +
    +
    + + {{ form.owner }} +
    +
    +
    {% endblock content %} diff --git a/staff/templates/create_student_user.html b/staff/templates/create_student_user.html index 2fd0163..537a95a 100644 --- a/staff/templates/create_student_user.html +++ b/staff/templates/create_student_user.html @@ -1,19 +1,60 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} -
    - -
    - -
    -

    Create Student User

    -
    +
    +
    + {% include "error.html" %} + + Create Student User {% csrf_token %} - {{ form|crispy }} -
    - +
    + + {{ form.first_name }} +
    +
    + + {{ form.last_name }} +
    +
    + + {{ form.email }} +
    +
    + + {{ form.birthdate }} +
    +
    + + {{ form.expected_graduation_year }} +
    +
    + + {{ form.race }} +
    +
    + + {{ form.which_best_describes_your_ethnicity }} +
    +
    + + {{ form.gender }} +
    +
    + + {{ form.title }} +
    +
    + + {{ form.account }} +
    +
    + + {{ form.owner }} +
    +
    +
    {% endblock content %} diff --git a/staff/templates/create_teacher_user.html b/staff/templates/create_teacher_user.html index c251ab4..8e9df87 100644 --- a/staff/templates/create_teacher_user.html +++ b/staff/templates/create_teacher_user.html @@ -1,19 +1,56 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} -
    - -
    - -
    -

    Create Teacher User

    -
    +
    +
    + {% include "error.html" %} + + Create Teacher User {% csrf_token %} - {{ form|crispy }} -
    - +
    + + {{ form.first_name }} +
    +
    + + {{ form.last_name }} +
    +
    + + {{ form.email }} +
    +
    + + {{ form.birthdate }} +
    +
    + + {{ form.race }} +
    +
    + + {{ form.which_best_describes_your_ethnicity }} +
    +
    + + {{ form.gender }} +
    +
    + + {{ form.title }} +
    +
    + + {{ form.account }} +
    +
    + + {{ form.owner }} +
    +
    +
    {% endblock content %} diff --git a/staff/templates/create_volunteer_user.html b/staff/templates/create_volunteer_user.html index 3fe441f..8f953f9 100644 --- a/staff/templates/create_volunteer_user.html +++ b/staff/templates/create_volunteer_user.html @@ -1,20 +1,57 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} -
    - -
    - -
    -

    Create Volunteer User

    -
    +
    +
    + {% include "error.html" %} + + Create Volunteer User {% csrf_token %} - {{ form|crispy }} -
    - +
    + + {{ form.first_name }} +
    +
    + + {{ form.last_name }} +
    +
    + + {{ form.email }} +
    +
    + + {{ form.birthdate }} +
    +
    + + {{ form.race }} +
    +
    + + {{ form.which_best_describes_your_ethnicity }} +
    +
    + + {{ form.gender }} +
    +
    + + {{ form.title }} +
    +
    + + {{ form.account }} +
    +
    + + {{ form.owner }} +
    +
    +
    {% endblock content %} diff --git a/staff/templates/curriculum.html b/staff/templates/curriculum.html index 24acc17..8be3581 100644 --- a/staff/templates/curriculum.html +++ b/staff/templates/curriculum.html @@ -1,83 +1,30 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} - - - - -
    - -
    - -
    -

    {{ classroom.course }}'s Curriculum



    - - {% if sessions %} - - - - - - - - {% for session in sessions %} - - - - - - - {% endfor %} -
    DateTitleDescriptionModify
    {{ session.date }}{{ session.title }}{{ session.description }}
    - {% csrf_token %} - - - - -
    - {% endif %} - +
    +
    +

    {{ classroom.course }}'s Curriculum



    + {% if sessions %} + + + + + + + + {% for session in sessions %} + + + + + + + {% endfor %} +
    DateTitleDescriptionModify
    {{ session.date }}{{ session.title }}{{ session.description }}View/Change Curriculum +
    + {% endif %} +
    {% endblock content %} diff --git a/staff/templates/form_overview.html b/staff/templates/form_overview.html index 4a9f558..abe9f84 100644 --- a/staff/templates/form_overview.html +++ b/staff/templates/form_overview.html @@ -1,90 +1,49 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} - - - - - - - -
    -

    Form Overview

    -

    +

    Form Overview


    {% if outstanding_form_dict %} {% for form_name, distributions in outstanding_form_dict.items %} - -

    {{ form_name }}

    - - - - - - - - {% for distribution in distributions %} - - - - - - - - - - {% endfor %} -
    Form NameDistributionSubmittedCollect
    {{ form_name }}{{ distribution.user.first_name }} {{ distribution.user.last_name }}{{ distribution.submitted }} -
    - {% csrf_token %} {{ form|crispy }} - - -
    -
    -
    - -
    -
    +
    +
    + +

    {{ form_name }}

    + + + + + + + {% for distribution in distributions %} + + + + + + + {% endfor %} +
    Form NameDistributionSubmitted
    {{ form_name }}{{ distribution.user.first_name }} {{ distribution.user.last_name }}{{ distribution.submitted }} +
    +
    + {% csrf_token %} + Submitted:   {{ form.submitted }}    + + + +
    +
    +
    + Notify Unsubmitted Users +
    +
    {% endfor %} - {% else %} + {% else %}

    No outstanding Forms

    {% endif %} -
    {% endblock content %} diff --git a/staff/templates/make_announcement.html b/staff/templates/make_announcement.html index 4f0e459..a758291 100644 --- a/staff/templates/make_announcement.html +++ b/staff/templates/make_announcement.html @@ -1,19 +1,40 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} - -
    - -
    - -
    -

    Make Announcement

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - +
    +
    + {% include "error.html" %} + + {% csrf_token %} + Announcement
    +
    + {{ form.title }} + +
    +
    + {{ form.announcement }} + +

    +
    +
    +
    + + {{ form.recipient_groups }} +

    +
    + + {{ form.recipient_classrooms }} +

    +
    + + {{ form.email_recipients }} +

    +
    +
    +
    + +
    +
    {% endblock content %} diff --git a/staff/templates/modify_session.html b/staff/templates/modify_session.html index 40ec7fd..9c0d8b3 100644 --- a/staff/templates/modify_session.html +++ b/staff/templates/modify_session.html @@ -1,113 +1,79 @@ -{% extends "staff_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} - - - -
    + {% include "error.html" %} +

    {{ classroom.course }} - {{ date }}


    +
    + {% csrf_token %} + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
    Field NameCurrent ValueModifyChange
    Session Title{{ session.title }} +
    + {{ form.title }} + +
    +
    Session Description{{ session.description }} +
    + {{ form.description }} + +
    +
    Lesson Plan{{ session.lesson_plan }}{{ form.lesson_plan }}
    Lecture{{ session.lecture }}{{ form.lecture }}
    Activity{{ session.activity }}{{ form.activity }}
    Video{{ session.video }} +
    + {{ form.video}} + +
    +

    + + +
    +
    -
    -

    {{ classroom.course }} - {{ date }}


    -

    Modify Session



    -
    - {% csrf_token %} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
    Field NameCurrent ValueModifyChange
    Session Title{{ session.title }}{{ form.title }}
    Session Description{{ session.description }}{{ form.description }}
    Lesson Plan{{ session.lesson_plan }}{{ form.lesson_plan }}
    Lecture{{ session.lecture }}{{ form.lecture }}
    Activity{{ session.activity }}{{ form.activity }}
    Video{{ session.video }}{{ form.video }}

    - - -
    - -
    {% endblock content %} diff --git a/staff/templates/my_account_staff.html b/staff/templates/my_account_staff.html deleted file mode 100644 index 9a40a8a..0000000 --- a/staff/templates/my_account_staff.html +++ /dev/null @@ -1,7 +0,0 @@ -{% extends "staff_base.html" %} - -{% block content %} - -

    My Account

    - -{% endblock content %} \ No newline at end of file diff --git a/staff/templates/notify_unsubmitted_users.html b/staff/templates/notify_unsubmitted_users.html index 61dd523..ab61f4b 100644 --- a/staff/templates/notify_unsubmitted_users.html +++ b/staff/templates/notify_unsubmitted_users.html @@ -1,20 +1,35 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} - - -
    -

    Notify Users About {{ notify_about }}

    -
    +
    +
    + {% include "error.html" %} + + Notify Users About "{{ notify_about }}"
    {% csrf_token %} - {{ form|crispy }} -
    - - +
    + {{ form.subject }} + +
    +
    + {{ form.notification }} + +
    +
    +
    +
    + + {{ form.email_recipients }} +

    +
    +
    +
    + + -
    +
    +
    + {% endblock content %} diff --git a/staff/templates/post_form.html b/staff/templates/post_form.html index 6e9f925..10b0e7a 100644 --- a/staff/templates/post_form.html +++ b/staff/templates/post_form.html @@ -1,19 +1,49 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% load crispy_forms_tags %} {% block content %} - - -
    -

    Post a Form

    -
    - {% csrf_token %} - {{ form|crispy }} -
    - -
    +
    +
    + {% include "error.html" %} +
    + Post Form + {% csrf_token %} +
    + {{ form.name }} + +
    +
    + {{ form.description }} + +
    +
    +
    + {{ form.form }} +
    +
    +
    + {{ form.esign }} +
    +
    +
    +
    + + {{ form.recipient_groups }} +

    +
    + + {{ form.recipient_classrooms }} +

    +
    + + {{ form.email_recipients }} +

    +
    +
    + +
    +
    + {% endblock content %} diff --git a/staff/templates/staff.html b/staff/templates/staff.html index dffc319..c48d2e1 100644 --- a/staff/templates/staff.html +++ b/staff/templates/staff.html @@ -1,114 +1,19 @@ -{% extends "staff_base.html" %} +{% extends "base.html" %} {% block content %} - - - - - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} -

    Staff User Home


    +
    + {% include "message.html" %} +

    Staff User Home


    {% if announcements %} -

    Announcements


    - {% for announcement in announcements reversed %} -
    -

    {{ announcement.announcement.title }}


    -

    {{ announcement.announcement.announcement }}


    -

    {{ announcement.announcement.created_by }} on {{ announcement.announcement.posted.date }}


    -
    - {% csrf_token %} - - -

    -
    -

    - {% endfor %} + {% include "announcements.html" %} {% endif %} {% if forms %} -

    Forms


    - {% for form in forms reversed %} -
    -

    {{ form.form.name }}


    -

    {{ form.form.description }}


    -

    {{ form.form.created_by }} on {{ form.form.posted.date }}



    - {% if form.form.esign != NULL %} -

    Esign Here


    - {% endif %} -

    - Download Form -

    -

    - {% endfor %} + {% include "forms.html" %} {% endif %} {% if notifications %} -

    Notifications


    - {% for notification in notifications %} -
    -

    {{ notification.subject }}


    -

    {{ notification.notification }}


    -

    Mission Bit on {{ notification.notified.date }}


    -

    -

    - {% csrf_token %} - - -

    -
    -

    -

    - {% endfor %} + {% include "notifications.html" %} {% endif %} -
    - - - +
    {% endblock content %} diff --git a/staff/templates/staff_base.html b/staff/templates/staff_base.html deleted file mode 100644 index cc67448..0000000 --- a/staff/templates/staff_base.html +++ /dev/null @@ -1,82 +0,0 @@ -{% load static %} - - - - Mission Bit - - - - - - - - - - - - - - -{% block content %} - - -{% endblock %} - - - - diff --git a/staff/templates/user_management.html b/staff/templates/user_management.html deleted file mode 100644 index b629cbf..0000000 --- a/staff/templates/user_management.html +++ /dev/null @@ -1,24 +0,0 @@ -{% extends "staff_base.html" %} - -{% block content %} - - - -
    -

    User Management Home

    - - {% if names %} - {% for name in names %} -

    {{ name }}

    - {% endfor %} - {% endif %} - -
    - - -{% endblock content %} diff --git a/staff/templatetags/__init__.py b/staff/templatetags/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/staff/templatetags/settings_tags.py b/staff/templatetags/settings_tags.py new file mode 100644 index 0000000..4e2b350 --- /dev/null +++ b/staff/templatetags/settings_tags.py @@ -0,0 +1,9 @@ +from django import template +from django.conf import settings + +register = template.Library() + +# settings value +@register.simple_tag +def settings_value(name): + return getattr(settings, name, "") diff --git a/staff/urls.py b/staff/urls.py index ad684f5..2fc36fb 100644 --- a/staff/urls.py +++ b/staff/urls.py @@ -3,7 +3,6 @@ urlpatterns = [ path("", views.staff, name="staff"), - path("user_management/", views.user_management, name="user_management"), path( "classroom_management/", views.classroom_management, name="classroom_management" ), @@ -15,7 +14,6 @@ views.create_volunteer_user, name="create_volunteer_user", ), - path("my_account_staff/", views.my_account_staff, name="my_account_staff"), path("create_classroom/", views.create_classroom, name="create_classroom"), path( "create_class_offering/", @@ -26,10 +24,22 @@ path("post_form/", views.post_form, name="post_form"), path("create_esign", views.create_esign, name="create_esign"), path("form_overview", views.form_overview, name="form_overview"), - path("notify_unsubmitted_users", views.notify_unsubmitted_users, name="notify_unsubmitted_users"), - path("communication_manager/", views.communication_manager, name="communication_manager"), + path( + "notify_unsubmitted_users/", + views.notify_unsubmitted_users, + name="notify_unsubmitted_users", + ), + path( + "communication_manager/", + views.communication_manager, + name="communication_manager", + ), path("curriculum/", views.curriculum, name="curriculum"), - path("modify_session/", views.modify_session, name="modify_session"), + path( + "modify_session//", views.modify_session, name="modify_session" + ), path("add_forum/", views.add_forum, name="add_forum"), - path("classroom_detail/", views.classroom_detail, name="classroom_detail") + path( + "classroom_detail/", views.classroom_detail, name="classroom_detail" + ), ] diff --git a/staff/views.py b/staff/views.py index e749fff..cdb3d53 100644 --- a/staff/views.py +++ b/staff/views.py @@ -18,11 +18,10 @@ AddCurriculumForm, AddForumForm, AddVolunteerForm, - AddStudentForm + AddStudentForm, ) from .staff_views_helper import * from attendance.views import get_date_from_template_returned_string -from social_django.models import UserSocialAuth from home.models.models import Classroom, Form, Esign, Notification, Announcement import os @@ -31,22 +30,30 @@ def staff(request): if request.method == "POST": if request.POST.get("dismiss_announcement") == "true": - mark_announcement_dismissed(Announcement.objects.get(id=request.POST.get("announcement")), request.user) + mark_announcement_dismissed( + Announcement.objects.get(id=request.POST.get("announcement")), + request.user, + ) return redirect("staff") elif request.POST.get("acknowledge_notification") == "true": - mark_notification_acknowledged(Notification.objects.get(id=request.POST.get("notification"))) + mark_notification_acknowledged( + Notification.objects.get(id=request.POST.get("notification")) + ) return redirect("staff") announcements = get_my_announcements(request, "staff") forms = get_my_forms(request, "staff") - notifications = Notification.objects.filter(user_id=request.user.id, acknowledged=False) - return render(request, "staff.html", {"announcements": announcements, - "forms": forms, - "notifications": notifications}) - - -@group_required("staff") -def user_management(request): - return render(request, "user_management.html") + notifications = Notification.objects.filter( + user_id=request.user.id, acknowledged=False + ) + return render( + request, + "staff.html", + { + "announcements": announcements, + "forms": forms, + "notifications": notifications, + }, + ) @group_required("staff") @@ -55,8 +62,17 @@ def classroom_management(request): classroom_list = Classroom.objects.all() for classroom in classroom_list: class_dict.update({classroom.course: get_class_member_dict(classroom)}) - return render(request, "classroom_management.html", {"classrooms": classroom_list, - "class_dicts": class_dict}) + return render( + request, + "classroom_management.html", + { + "classrooms": classroom_list, + "class_dicts": class_dict, + "user_groups": set( + request.user.groups.all().values_list("name", flat=True) + ), + }, + ) @group_required("staff") @@ -64,33 +80,32 @@ def create_staff_user(request): if request.method == "POST": form = CreateStaffForm(request.POST) if form.is_valid(): - form.save() - random_password = DjangoUser.objects.make_random_password() - new_user = create_user_with_profile(form, random_password) - email = form.cleaned_data.get("email") - staff_group = Group.objects.get(name="staff") - staff_group.user_set.add(new_user) - UserSocialAuth.objects.create( - uid=form.cleaned_data.get("email"), - user_id=new_user.userprofile.user_id, - provider="google-oauth2", - ) - first_name = form.cleaned_data.get("first_name") - messages.success( - request, f"Staff Account Successfully Created For {first_name}" - ) - email_new_user( - request, email, first_name, "staff", new_user.username, random_password - ) + save_user_to_salesforce(request, form) + create_mission_bit_user(request, form, "staff") + messages.add_message(request, messages.SUCCESS, "Staff User Created") return redirect("staff") else: - messages.error( + return render( request, - "Staff User NOT created, your form was not valid, please try again.", + "create_staff_user.html", + { + "form": form, + "user_groups": set( + request.user.groups.all().values_list("name", flat=True) + ), + }, ) - return redirect("staff") form = CreateStaffForm() - return render(request, "create_staff_user.html", {"form": form}) + return render( + request, + "create_staff_user.html", + { + "form": form, + "user_groups": set( + request.user.groups.all().values_list("name", flat=True) + ), + }, + ) @group_required("staff") @@ -98,36 +113,12 @@ def create_teacher_user(request): if request.method == "POST": form = CreateTeacherForm(request.POST) if form.is_valid(): - form.save() - random_password = DjangoUser.objects.make_random_password() - new_user = create_user_with_profile(form, random_password) - email = form.cleaned_data.get("email") - teacher_group = Group.objects.get(name="teacher") - teacher_group.user_set.add(new_user) - UserSocialAuth.objects.create( - uid=form.cleaned_data.get("email"), - user_id=new_user.userprofile.user_id, - provider="google-oauth2", - ) - first_name = form.cleaned_data.get("first_name") - messages.success( - request, f"Teacher Account Successfully Created For {first_name}" - ) - email_new_user( - request, - email, - first_name, - "teacher", - new_user.username, - random_password, - ) + save_user_to_salesforce(request, form) + create_mission_bit_user(request, form, "teacher") + messages.add_message(request, messages.SUCCESS, "Teacher User Created") return redirect("staff") else: - messages.error( - request, - "Teacher User NOT created, your form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "create_teacher_user.html", {"form": form}) form = CreateTeacherForm() return render(request, "create_teacher_user.html", {"form": form}) @@ -138,35 +129,11 @@ def create_student_user(request): form = CreateStudentForm(request.POST) if form.is_valid(): form.save() - random_password = DjangoUser.objects.make_random_password() - new_user = create_user_with_profile(form, random_password) - email = form.cleaned_data.get("email") - student_group = Group.objects.get(name="student") - student_group.user_set.add(new_user) - UserSocialAuth.objects.create( - uid=form.cleaned_data.get("email"), - user_id=new_user.userprofile.user_id, - provider="google-oauth2", - ) - first_name = form.cleaned_data.get("first_name") - messages.success( - request, f"Student Account Successfully Created For {first_name}" - ) - email_new_user( - request, - email, - first_name, - "student", - new_user.username, - random_password, - ) + create_mission_bit_user(request, form, "student") + messages.add_message(request, messages.SUCCESS, "Student User Created") return redirect("staff") else: - messages.error( - request, - "Student User NOT created, your form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "create_student_user.html", {"form": form}) form = CreateStudentForm() return render(request, "create_student_user.html", {"form": form}) @@ -176,36 +143,12 @@ def create_volunteer_user(request): if request.method == "POST": form = CreateVolunteerForm(request.POST) if form.is_valid(): - form.save() - random_password = DjangoUser.objects.make_random_password() - new_user = create_user_with_profile(form, random_password) - email = form.cleaned_data.get("email") - volunteer_group = Group.objects.get(name="volunteer") - volunteer_group.user_set.add(new_user) - UserSocialAuth.objects.create( - uid=form.cleaned_data.get("email"), - user_id=new_user.userprofile.user_id, - provider="google-oauth2", - ) - first_name = form.cleaned_data.get("first_name") - messages.success( - request, f"Volunteer Account Successfully Created For {first_name}" - ) - email_new_user( - request, - email, - first_name, - "volunteer", - new_user.username, - random_password, - ) + save_user_to_salesforce(request, form) + create_mission_bit_user(request, form, "volunteer") + messages.add_message(request, messages.SUCCESS, "Volunteer User Created") return redirect("staff") else: - messages.error( - request, - "Volunteer User NOT created, your form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "create_volunteer_user.html", {"form": form}) form = CreateVolunteerForm() return render(request, "create_volunteer_user.html", {"form": form}) @@ -217,16 +160,11 @@ def create_classroom(request): if form.is_valid(): setup_classroom(request, form) messages.success( - request, - f'Classroom {form.cleaned_data.get("course")} Successfully Created', + request, f'{form.cleaned_data.get("course")} Successfully Created' ) return redirect("staff") else: - messages.error( - request, - "Classroom NOT created, your form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "create_classroom.html", {"form": form}) form = CreateClassroomForm() return render(request, "create_classroom.html", {"form": form}) @@ -242,11 +180,7 @@ def create_class_offering(request): ) return redirect("staff") else: - messages.error( - request, - "Class offering NOT created, your form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "create_class_offering.html", {"form": form}) form = CreateClassOfferingForm() return render(request, "create_class_offering.html", {"form": form}) @@ -270,11 +204,7 @@ def make_announcement(request): ) return redirect("staff") else: - messages.error( - request, - "Announcement NOT made, your announcement form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "make_announcement.html", {"form": form}) form = MakeAnnouncementForm( initial={"created_by": DjangoUser.objects.get(id=request.user.id)} ) @@ -299,21 +229,23 @@ def post_form(request): posted_form.recipient_classrooms.set( form.cleaned_data.get("recipient_classrooms") ) - messages.add_message(request, messages.SUCCESS, "Successfully Posted Form") user_list = get_users_from_form(form) email_list = [user.email for user in user_list] if form.cleaned_data.get("email_recipients"): subject = form.cleaned_data.get("name") message = form.cleaned_data.get("description") - email_posted_form(request, form.cleaned_data.get("esign", None), subject, message, email_list) + email_posted_form( + request, + form.cleaned_data.get("esign", None), + subject, + message, + email_list, + ) distribute_forms(request, posted_form, user_list) + messages.add_message(request, messages.SUCCESS, "Successfully Posted Form") return redirect("staff") else: - messages.error( - request, - "Form NOT made, your form form was not valid, please try again.", - ) - return redirect("staff") + return render(request, "post_form.html", {"form": form}) form = PostFormForm( initial={"created_by": DjangoUser.objects.get(id=request.user.id)} ) @@ -326,34 +258,51 @@ def form_overview(request): form = CollectForms(request.POST) if form.is_valid(): form_id = Form.objects.get(name=request.POST.get("form_name")) - form_distribution = FormDistribution.objects.get(user_id=request.POST.get("user_id"), form_id=form_id) + form_distribution = FormDistribution.objects.get( + user_id=request.POST.get("user_id"), form_id=form_id + ) form_distribution.submitted = form.cleaned_data.get("submitted") form_distribution.save() - return redirect("form_overview") + messages.add_message(request, messages.SUCCESS, "Collected Form") + return redirect("form_overview") + else: + return render(request, "form_overview.html", {"form": form}) outstanding_form_dict = get_outstanding_forms() form = CollectForms() - return render(request, "form_overview.html", {"outstanding_form_dict": outstanding_form_dict, - "form": form}) + return render( + request, + "form_overview.html", + {"outstanding_form_dict": outstanding_form_dict, "form": form}, + ) @group_required("staff") -def notify_unsubmitted_users(request): +def notify_unsubmitted_users(request, notify_about=None): if request.method == "POST": form = NotifyUnsubmittedUsersForm(request.POST) if form.is_valid(): + print("notify_about: ", request.POST.get("notify_about")) form_id = Form.objects.get(name=request.POST.get("notify_about")).id - form_distributions = FormDistribution.objects.filter(form_id=form_id, submitted=False) + form_distributions = FormDistribution.objects.filter( + form_id=form_id, submitted=False + ) for form_dist in form_distributions: create_form_notification(request, form, form_dist.user_id) if form.cleaned_data.get("email_recipients"): email_list = get_emails_from_form_distributions(form_distributions) email_form_notification(request, form, email_list) - messages.add_message(request, messages.SUCCESS, "Successfully Notified Users") + messages.add_message( + request, messages.SUCCESS, "Successfully Notified Users" + ) return redirect("staff") + else: + return render(request, "notify_unsubmitted_users.html", {"form": form}) form = NotifyUnsubmittedUsersForm() - notify_about = request.GET.get("notify_unsubmitted_users") - return render(request, "notify_unsubmitted_users.html", {"form": form, - "notify_about": notify_about}) + return render( + request, + "notify_unsubmitted_users.html", + {"form": form, "notify_about": notify_about}, + ) @group_required("staff") @@ -364,7 +313,7 @@ def create_form_notification(request, form, user_id): email_recipients=form.cleaned_data.get("email_recipients"), created_by=DjangoUser.objects.get(id=request.user.id), form_id=Form.objects.get(name=request.POST.get("notify_about")).id, - user_id=user_id + user_id=user_id, ) notification.save() @@ -383,9 +332,15 @@ def communication_manager(request): announcements = Announcement.objects.all() notifications = Notification.objects.all() forms = Form.objects.all() - return render(request, "communication_manager.html", {"announcements": announcements, - "notifications": notifications, - "forms": forms}) + return render( + request, + "communication_manager.html", + { + "announcements": announcements, + "notifications": notifications, + "forms": forms, + }, + ) @group_required("staff") @@ -396,11 +351,15 @@ def create_esign(request): esign = Esign( name=form.cleaned_data.get("name"), template=form.cleaned_data.get("link"), - created_by=DjangoUser.objects.get(id=request.user.id) + created_by=DjangoUser.objects.get(id=request.user.id), ) esign.save() - messages.add_message(request, messages.SUCCESS, "Esign Created Successfully") - return redirect("staff") + messages.add_message( + request, messages.SUCCESS, "Esign Created Successfully" + ) + return redirect("staff") + else: + return render(request, "create_esign.html", {"form": form}) form = CreateEsignForm( initial={"created_by": DjangoUser.objects.get(id=request.user.id)} ) @@ -416,117 +375,157 @@ def add_forum(request): classroom.forum_title = form.cleaned_data.get("forum_title") classroom.forum = form.cleaned_data.get("forum") classroom.save() + messages.add_message(request, messages.SUCCESS, "Forum Added Successfully") return redirect("staff") + else: + classroom = Classroom.objects.get(id=request.GET.get("classroom")) + return render( + request, "add_forum.html", {"form": form, "classroom": classroom} + ) classroom = Classroom.objects.get(id=request.GET.get("classroom")) form = AddForumForm() - return render(request, "add_forum.html", {"form": form, - "classroom": classroom}) - - -@group_required("staff") -def my_account_staff(request): - return render(request, "my_account_staff.html") + return render(request, "add_forum.html", {"form": form, "classroom": classroom}) @group_required("staff") def curriculum(request): classroom = Classroom.objects.get(id=request.GET.get("classroom_id")) sessions = Session.objects.filter(classroom_id=classroom.id).order_by("date") - return render(request, "curriculum.html", {"sessions": sessions, - "classroom": classroom}) + return render( + request, "curriculum.html", {"sessions": sessions, "classroom": classroom} + ) @group_required("staff") -def modify_session(request): +def modify_session(request, date=None, classroom=None): if request.method == "POST": form = AddCurriculumForm(request.POST, request.FILES) if form.is_valid(): update_session(request, form) + return redirect("classroom_management") + else: + date = request.GET.get("date") + classroom = Classroom.objects.get(id=request.GET.get("classroom")) + session = Session.objects.get( + classroom_id=request.GET.get("classroom"), + date=get_date_from_template_returned_string(request.GET.get("date")), + ) + return render( + request, + "modify_session.html", + { + "form": form, + "date": date, + "classroom": classroom, + "session": session, + }, + ) form = AddCurriculumForm() - date = request.GET.get("date") - classroom = Classroom.objects.get(id=request.GET.get("classroom")) - session = Session.objects.get(classroom_id=request.GET.get("classroom"), - date=get_date_from_template_returned_string(request.GET.get("date"))) - return render(request, "modify_session.html", {"form": form, - "date": date, - "classroom": classroom, - "session": session}) + date = date + course = Classroom.objects.get(id=classroom) + session = Session.objects.get(classroom=classroom, date=date) + return render( + request, + "modify_session.html", + {"form": form, "date": date, "classroom": course, "session": session}, + ) @group_required("staff") -def classroom_detail(request): +def classroom_detail(request, course_id): if request.method == "POST": if request.POST.get("swap_teacher"): form = ChangeTeacherForm(request.POST) if form.is_valid(): - change_classroom_lead(request.POST.get("fmr_teacher", None), - form.cleaned_data.get("teacher").id, - request.POST.get("course_id", None), - "teacher") - messages.add_message(request, messages.SUCCESS, "Teacher Successfully Changed") + change_classroom_lead( + request.POST.get("fmr_teacher", None), + form.cleaned_data.get("teacher").id, + request.POST.get("course_id", None), + "teacher", + ) + messages.add_message( + request, messages.SUCCESS, "Teacher Successfully Changed" + ) return redirect("staff") else: - messages.add_message(request, messages.ERROR, "Invalid Form") # Need to have fall through here - return redirect("staff") + return render(request, "classroom_detail.html", {"form": form}) if request.POST.get("swap_teacher_assistant"): form = ChangeTeacherForm(request.POST) if form.is_valid(): - change_classroom_lead(request.POST.get("fmr_teacher_assistant", None), - form.cleaned_data.get("teacher").id, - request.POST.get("course_id", None), - "teacher_assistant") - messages.add_message(request, messages.SUCCESS, "Teacher Assistant Successfully Changed") + change_classroom_lead( + request.POST.get("fmr_teacher_assistant", None), + form.cleaned_data.get("teacher").id, + request.POST.get("course_id", None), + "teacher_assistant", + ) + messages.add_message( + request, messages.SUCCESS, "Teacher Assistant Successfully Changed" + ) return redirect("staff") else: - messages.add_message(request, messages.ERROR, "Invalid Form") # Need to have fall through here - return redirect("staff") + return render(request, "classroom_detail.html", {"form": form}) if request.POST.get("remove_student"): # Input Validation Needed - remove_user_from_classroom(request.POST["fmr_student"], request.POST["course_id"]) - messages.add_message(request, messages.SUCCESS, "Student Successfully Removed From Class") + remove_user_from_classroom( + request.POST["fmr_student"], request.POST["course_id"] + ) + messages.add_message( + request, messages.SUCCESS, "Student Successfully Removed From Class" + ) return redirect("staff") if request.POST.get("remove_volunteer"): # Input Validation Needed - remove_user_from_classroom(request.POST["fmr_volunteer"], request.POST["course_id"]) - messages.add_message(request, messages.SUCCESS, "Volunteer Successfully Removed From Class") + remove_user_from_classroom( + request.POST["fmr_volunteer"], request.POST["course_id"] + ) + messages.add_message( + request, messages.SUCCESS, "Volunteer Successfully Removed From Class" + ) return redirect("staff") if request.POST.get("add_volunteer"): form = AddVolunteerForm(request.POST) if form.is_valid(): - add_user_to_classroom(form.cleaned_data.get("volunteer").id, request.POST["course_id"], "volunteer") - messages.add_message(request, messages.SUCCESS, "Volunteer Added To Class") + add_user_to_classroom( + form.cleaned_data.get("volunteer").id, + request.POST["course_id"], + "volunteer", + ) + messages.add_message( + request, messages.SUCCESS, "Volunteer Added To Class" + ) return redirect("staff") else: - messages.add_message(request, messages.ERROR, "Invalid Form") # Need to have fall through here - return redirect("staff") + return render(request, "classroom_detail.html", {"form": form}) if request.POST.get("add_student"): form = AddStudentForm(request.POST) if form.is_valid(): - add_user_to_classroom(form.cleaned_data.get("student").id, request.POST["course_id"], "student") - messages.add_message(request, messages.SUCCESS, "Student Added To Class") + add_user_to_classroom( + form.cleaned_data.get("student").id, + request.POST["course_id"], + "student", + ) + messages.add_message( + request, messages.SUCCESS, "Student Added To Class" + ) return redirect("staff") else: - messages.add_message(request, messages.ERROR, "Invalid Form") # Need to have fall through here + messages.add_message( + request, messages.ERROR, "Invalid Form" + ) # Need to have fall through here return redirect("staff") - classroom = Classroom.objects.get(id=request.GET.get("course_id")) + classroom = Classroom.objects.get(id=course_id) class_members = get_class_member_dict(classroom) - return render(request, "classroom_detail.html", {"change_teacher_form": ChangeTeacherForm(), - "add_volunteer_form": AddVolunteerForm(), - "add_student_form": AddStudentForm(), - "classroom": classroom, - "class_members": class_members}) + return render( + request, + "classroom_detail.html", + { + "change_teacher_form": ChangeTeacherForm(), + "add_volunteer_form": AddVolunteerForm(), + "add_student_form": AddStudentForm(), + "classroom": classroom, + "class_members": class_members, + }, + ) @register.filter def get_item(dictionary, key): return dictionary.get(key) - - -@group_required("staff") -def download_form_staff(request): - path = request.GET.get("path") - file_path = os.path.join(path) - if os.path.exists(file_path): - with open(file_path, 'rb') as fh: - response = HttpResponse(fh.read(), content_type="pdf/text") - response['Content-Disposition'] = 'inline; filename=' + os.path.basename(file_path) - return response - raise Http404 diff --git a/static/close.svg b/static/close.svg new file mode 100644 index 0000000..f657dc2 --- /dev/null +++ b/static/close.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/static/css/errors_and_messages.css b/static/css/errors_and_messages.css new file mode 100644 index 0000000..eca9210 --- /dev/null +++ b/static/css/errors_and_messages.css @@ -0,0 +1,26 @@ +.alert-danger{ + display: inline-block; + height: 40px; + font-size: 16px; + background-color: #e74c3c; +} +.close { + float:right; + display:inline-block; + background: none; + padding-right: 10px; +} +.close:hover { + float:right; + display:inline-block; + background: none; + cursor: pointer; +} +.delete-icon{ + height: 20px; + width: 20px; +} +.delete-icon:hover{ + height: 21px; + width: 21px; +} diff --git a/static/css/landing_pg.css b/static/css/landing_pg.css new file mode 100644 index 0000000..3a4995d --- /dev/null +++ b/static/css/landing_pg.css @@ -0,0 +1,68 @@ + .mui--text-title{ + color: whitesmoke; + } + + .mui--text-right{ + color: whitesmoke; + } + + .logo{ + width: 50%; + } + + td{ + align-items: center; + } + + .loginBtn { + box-sizing: border-box; + position: relative; + margin: 0.2em; + padding: 0 15px 0 46px; + border: none; + text-align: left; + line-height: 34px; + white-space: nowrap; + border-radius: 0.2em; + font-size: 14px; + color: #FFF; + } + + .loginBtn:before { + content: ""; + box-sizing: border-box; + position: absolute; + top: 0; + left: 0; + width: 34px; + height: 100%; + } + + .loginBtn:focus { + outline: none; + } + + .loginBtn:active { + box-shadow: inset 0 0 0 32px rgba(0,0,0,0.1); + } + + .loginBtn--google { + font-family: "Roboto", Roboto, arial, sans-serif; + text-transform: uppercase; + background: #DD4B39; + } + + .loginBtn--google:before { + border-right: #BB3F30 1px solid; + background: url('/static/static-google-icon.png') 4px 6px no-repeat; + } + + .loginBtn--google:hover, + .loginBtn--google:focus { + background: #E74B37; + } + + .footer{ + background-color: #5c5c5c; + text-align: center; + } diff --git a/static/css/mui_assets.css b/static/css/mui_assets.css new file mode 100644 index 0000000..1a48907 --- /dev/null +++ b/static/css/mui_assets.css @@ -0,0 +1,419 @@ +html, +body { + height: 100%; + background-color: #eee; + font-family: 'Montserrat', sans-serif; +} + +html, +body, +input, +textarea, +button { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004); +} + +.rightpanelbody-hidden{ + background-color: whitesmoke; + height: 100%; + position: fixed; + width: 35%; + transform: translate(100%); + transition: transform .2s ease-out; + top: 64px; + right: 0; + z-index: 1; +} + +.rightpanelbody-visible{ + background-color: whitesmoke; + width: 35%; + transform: translate(0); + transition: transform .3s ease-out; + position: fixed; + top: 64px; + right: 0; + height:calc(100% - 65px); + overflow-x: auto; + overflow-y: auto; + box-shadow: 0px 3px 10px gray; + z-index: 1; +} + +.mui-container-fluid{ + z-index: 3; +} + +.row:after { + content: ""; + display: table; + clear: both; +} + +/* The expanding image container */ +.img-display-container { + position: relative; + display: none; +} + +/* Expanding image text */ +#imgtext { + position: absolute; + bottom: 15px; + left: 15px; + color: white; + font-size: 20px; +} + +/** + * Layout CSS + */ +#header { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 2; + transition: left 0.2s; +} + +.instafeedcontent{ + width: 90%; + border-radius: 35px 35px 35px 35px; + opacity: 0.6; + transition: all 0.3s ease 0s; + filter: alpha(opacity=80); + display: inline-block; +} + +.instafeedcontent:hover{ + opacity: 1; + filter: alpha(opacity=100); + box-shadow: 0px 0px 10px 8px lightgray; + border-radius: 10px 10px 10px 10px; +} + +.slot-description{ + color: gray; + text-align: center; + vertical-align: top; + font-size: 24px; +} + +#sidedrawer { + position: fixed; + top:0; + bottom: 0; + width: 200px; + left: -200px; + overflow: auto; + z-index: 2; + background-color: #fff; + transition: all 0.3s ease 0s; +} + +#content-wrapper { + min-height: 100%; + overflow-x: hidden; + margin-left: 0px; + transition: margin-left 0.2s; + + /* sticky bottom */ + margin-bottom: -160px; + padding-bottom: 160px; +} + +#footer { + height: 160px; + margin-left: 0px; + transition: margin-left 0.2s; + z-index: 200; +} + +@media (max-width: 767px) { + #expandedImg{ + width:63% + } + + + + .mui-panel{ + width: 80%; + } +} + + +@media (min-width: 768px) { + + .mui-panel{ + width: 50%; + } + + #expandedImg{ + width:45% + } + + + #header { + left: 200px; + } + + #sidedrawer { + transform: translate(200px); + } + + + #expandedImg{ + width: 30%; + } + + #content-wrapper { + margin-left: 200px; + } + + #footer { + margin-left: 200px; + } + + body.hide-sidedrawer #header { + left: 0; + } + + body.hide-sidedrawer #sidedrawer { + transform: translate(0px); + } + + + body.hide-sidedrawer #content-wrapper { + margin-left: 0; + } + + body.hide-sidedrawer #footer { + margin-left: 0; + } +} + +/** + * Toggle Side drawer + */ +#sidedrawer.active { + transform: translate(200px); +} + +/** + * Header CSS + */ +.sidedrawer-toggle { + color: #fff; + cursor: pointer; + font-size: 32px; + line-height: 20px; + margin-right: 20px; +} + + +.sidedrawer-toggle:hover { + color: #fff; + text-decoration: none; +} + +/** + * Footer CSS + */ +#footer { + background-color: #0288D1; + color: #fff; +} + +#footer a { + color: #fff; + text-decoration: underline; +} + +.material-icons { + font-family: 'Material Icons', sans-serif; + font-weight: normal; + font-style: normal; + font-size: 24px; /* Preferred icon size */ + display: inline-block; + line-height: 1; + text-transform: none; + letter-spacing: normal; + word-wrap: normal; + white-space: nowrap; + direction: ltr; + + /* Support for all WebKit browsers. */ + -webkit-font-smoothing: antialiased; + /* Support for Safari and Chrome. */ + text-rendering: optimizeLegibility; + + /* Support for Firefox. */ + -moz-osx-font-smoothing: grayscale; + + /* Support for IE. */ + font-feature-settings: 'liga'; +} + +.sidenav-content a{ + position: relative; + height: 30px; + text-align: center; + padding-top: 20px; + padding-left: 5px; + text-decoration: #333333; + color: steelblue; + display: block; + transition: all 0.3s ease 0s; +} + +.sidenav-content a:hover { + color: #ffffff; + padding-left: 10px; + padding-bottom: 16px; + background: gray; + overflow: hidden; +} + +.mainslide{ + font-weight: bold; + font-size: 21px; +} + +.mainslide:hover { + color: #ffffff; + padding-left: 10px; + padding-bottom: 18px; + background: gray; + overflow: hidden; +} + +.announcement { + padding: 10px 15px 0px; + background-color: #3498db; + border-radius: 14px 14px 14px 14px; + color: white; + font-size: 20px; + box-shadow: 3px 3px 12px 5px lightgray; +} + +.form { + padding: 10px 15px 0px; + background-color: #8e44ad; + border-radius: 14px 14px 14px 14px; + font-size: 20px; + color: white; + box-shadow: 3px 3px 12px 5px lightgray; + overflow: hidden; +} + +.notification { + padding: 10px 15px 0px; + background-color: #e67e22; + border-radius: 14px 14px 14px 14px; + color: white; + transition: all 0.3s ease 0s; + box-shadow: 3px 3px 12px 5px lightgray; + font-size: 20px; +} + +.appbarnav { + color: white; + font-size: 20px; + padding-left: 15px; + transition: all 0.2s ease 0s; +} + +.appbarnav:hover{ + color: lightskyblue; + text-decoration: none; +} + +.alert{ + padding-left: 5px; + vertical-align: center; + background-color: #4CAF50; + height: 40px; + width: 500px; + font-size: 25px; + border-radius: 14px 14px 14px 14px; +} + +.alert-close{ + display: none; +} + +.sidenav-content section div a{ + padding-bottom: 12px; + font-size: 15px; + height: 22px; +} + +.sidenav-content section div a:hover{ + background-color: lightgray; + height: 22px; + color: black; + padding-bottom: 20px; +} + +.intro div{ + display: none; +} +.deintro div{ + display: block; +} + +.videoblock{ + display: flex; + align-items: center; + justify-content:center; +} +.videoblock:hover>.controls{ + display: flex; + transition: all 0.3s ease 0s; + opacity: 1 +} + +.controls{ + display: flex; + position: absolute; + color: whitesmoke; + transition: all 0.3s ease 0s; + opacity: 0 +} + +.controls:hover{ + cursor: pointer; +} + +.c-video{ + border-radius: 45px 45px 45px 45px +} + +.notification-container { + text-align: center; +} + +.notification-container > .mui-panel { + display: inline-block; +} + +.form-container { + text-align: center; +} + +.form-container > .mui-panel { + width: 45%; + display: inline-block; +} + +.table-container { + text-align: center; +} + +.table-container > .mui-panel { + width: 85%; + display: inline-block; +} diff --git a/static/css/style.css b/static/css/style.css new file mode 100644 index 0000000..ff5dfe8 --- /dev/null +++ b/static/css/style.css @@ -0,0 +1,68 @@ +/** + * Body CSS + */ + +html, +body { + height: 100%; +} + +html, +body, +input, +textarea, +button { + -webkit-font-smoothing: antialiased; + -moz-osx-font-smoothing: grayscale; + text-shadow: 1px 1px 1px rgba(0, 0, 0, 0.004); +} + + +/** + * Header CSS + */ +header { + position: fixed; + top: 0; + right: 0; + left: 0; + z-index: 2; +} + +header ul.mui-list--inline { + margin-bottom: 0; +} + +header a { + color: #fff; +} + +header table { + width: 100%; +} + + +/** + * Content CSS + */ +#content-wrapper { + min-height: 100%; + + /* sticky footer */ + box-sizing: border-box; + margin-bottom: -100px; + padding-bottom: 100px; +} + + +/** + * Footer CSS + */ +footer { + box-sizing: border-box; + height: 100px; + background-color: #eee; + border-top: 1px solid #e0e0e0; + padding-top: 35px; +} + diff --git a/static/insta-comment.png b/static/insta-comment.png new file mode 100644 index 0000000..d6c3311 Binary files /dev/null and b/static/insta-comment.png differ diff --git a/static/insta-heart.png b/static/insta-heart.png new file mode 100644 index 0000000..b318904 Binary files /dev/null and b/static/insta-heart.png differ diff --git a/static/insta-icon.jpg b/static/insta-icon.jpg new file mode 100644 index 0000000..0fa1af3 Binary files /dev/null and b/static/insta-icon.jpg differ diff --git a/static/logo.svg b/static/logo.svg new file mode 100755 index 0000000..989a5da --- /dev/null +++ b/static/logo.svg @@ -0,0 +1,197 @@ + + + + diff --git a/static/missionbit-icon.png b/static/missionbit-icon.png new file mode 100644 index 0000000..f7eb2b9 Binary files /dev/null and b/static/missionbit-icon.png differ diff --git a/static/missionbit-logo.png b/static/missionbit-logo.png new file mode 100644 index 0000000..99b7c21 Binary files /dev/null and b/static/missionbit-logo.png differ diff --git a/static/static-google-icon.png b/static/static-google-icon.png new file mode 100644 index 0000000..ae7f045 Binary files /dev/null and b/static/static-google-icon.png differ diff --git a/student/templates/attendance_student.html b/student/templates/attendance_student.html index f2d69a7..51bee0b 100644 --- a/student/templates/attendance_student.html +++ b/student/templates/attendance_student.html @@ -1,47 +1,25 @@ -{% extends "student_base.html" %} +{% extends "base.html" %} {% block content %} - - - - - -
    -

    {{ classroom.course }}

    -

    My Attendance - {{ attendance_percentage }}%

    - - - - - - - {% for attendance_day in attendance %} - - - - - - {% endfor %} -
    DateStatusSession
    {{ attendance_day.date }}{{ attendance_day.presence }}{{ attendance_day.session.title }}
    +
    +
    +

    {{ classroom.course }}

    +

    My Attendance - {{ attendance_percentage }}%

    + + + + + + + {% for attendance_day in attendance %} + + + + + + {% endfor %} +
    DateStatusSession
    {{ attendance_day.date }}{{ attendance_day.presence }}{{ attendance_day.session.title }}
    +
    - {% endblock content %} diff --git a/student/templates/my_class_student.html b/student/templates/my_class_student.html index 525ce62..a9579d0 100644 --- a/student/templates/my_class_student.html +++ b/student/templates/my_class_student.html @@ -1,82 +1,32 @@ -{% extends "student_base.html" %} +{% extends "base.html" %} {% block content %} - - - - - -
    -

    {{ classroom.course }}


    - {% if sessions %} - - - - - - - - {% for session in sessions %} - - - - - - - {% endfor %} -
    DateTitleDescriptionView Session
    {{ session.date }}{{ session.title }}{{ session.description }} -
    - - - -
    -
    - {% endif %} -
    - +
    +
    +

    {{ classroom.course }}


    + {% if sessions %} + + + + + + + {% for session in sessions %} + + + + + + {% endfor %} +
    DateTitleView Session
    {{ session.date }}{{ session.title }} +
    + + + +
    +
    + {% endif %} +
    +
    {% endblock content %} diff --git a/student/templates/session_view_student.html b/student/templates/session_view_student.html index ebd62bc..54613dc 100644 --- a/student/templates/session_view_student.html +++ b/student/templates/session_view_student.html @@ -1,90 +1,44 @@ -{% extends "student_base.html" %} -{% load crispy_forms_tags %} +{% extends "base.html" %} {% block content %} - - - - - -
    -

    My Class


    - {% if session %} -

    {{ session.title }} - {{ session.date }}


    -
    -

    Description


    -

    {{ session.description }}


    -

    Lesson Plan


    - {% if session.lesson_plan %} - Download Lesson Plan -
    - {% else %} -

    No Lesson Plan Available


    - {% endif %} -

    Lecture


    - {% if session.lecture %} - Download Lecture -
    +
    +
    +

    {{ classroom.course }} - {{ session.date }}


    + {% if session %} +

    {{ session.title }}

    +
    +

    Description


    +

    {{ session.description }}


    +

    Activity


    + {% if session.activity %} + Download Activity +
    + {% else %} +

    No Activity Available


    + {% endif %} +

    Video


    + {% if session.video %} + View Session Video
    {% else %} -

    No Lecture Available


    +

    No Video Available


    {% endif %} -

    Activity


    - {% if session.activity %} - Download Activity -
    +

    Resources


    + {% if resources %} + {% for resource in resources %} +
    {{ resource.title }}
    + {% if resource.file %} + Download Resource +
    + {% endif %} + {% if resource.link %} + Go To Resource
    + {% endif %} + {% endfor %} {% else %} -

    No Activity Available


    +

    No Resources


    {% endif %} -

    Video


    - {% if session.video %} - View Session Video
    - {% else %} -

    No Video Available


    - {% endif %} -

    Resources


    - {% if resources %} - {% for resource in resources %} -
    {{ resource.title }}
    - {% if resource.file %} - Download Resource -
    - {% endif %} - {% if resource.link %} - Go To Resource
    - {% endif %} - {% endfor %} - {% else %} -

    No Resources


    - {% endif %} - {% endif %} + {% endif %} +
    - {% endblock content %} diff --git a/student/templates/student.html b/student/templates/student.html index 600e2cc..c48d2e1 100644 --- a/student/templates/student.html +++ b/student/templates/student.html @@ -1,103 +1,19 @@ -{% extends "student_base.html" %} +{% extends "base.html" %} {% block content %} - - - - - -
    - {% if messages %} - {% for message in messages %} -
    - {{ message }} -
    - {% endfor %} - {% endif %} -

    Student User Home


    +
    + {% include "message.html" %} +

    Staff User Home


    {% if announcements %} -

    Announcements


    - {% for announcement in announcements reversed %} -
    -

    {{ announcement.announcement.title }}


    -

    {{ announcement.announcement.announcement }}


    -

    {{ announcement.announcement.created_by }} on {{ announcement.announcement.posted.date }}


    -
    - {% csrf_token %} - - -

    -
    -

    - {% endfor %} + {% include "announcements.html" %} {% endif %} - {% if forms %} -

    Forms


    - {% for form in forms %} -
    -

    {{ form.form.name }}


    -

    {{ form.form.created_by }} on {{ form.form.posted.date }}


    -

    - Download Form -

    -

    - {% endfor %} + {% include "forms.html" %} {% endif %} {% if notifications %} -

    Notifications


    - {% for notification in notifications %} -
    -

    {{ notification.subject }}


    -

    {{ notification.notification }}


    -

    Mission Bit on {{ notification.notified.date }}


    -

    -

    - {% csrf_token %} - - -

    -
    -

    -

    - {% endfor %} + {% include "notifications.html" %} {% endif %} -
    +
    {% endblock content %} diff --git a/student/templates/student_base.html b/student/templates/student_base.html deleted file mode 100644 index 955ccbf..0000000 --- a/student/templates/student_base.html +++ /dev/null @@ -1,74 +0,0 @@ -{% load static %} - - - - Mission Bit - - - - - - - - - - - - -{% block content %} - - -{% endblock %} - - - - diff --git a/student/urls.py b/student/urls.py index 8160acf..45b0f03 100644 --- a/student/urls.py +++ b/student/urls.py @@ -1,7 +1,11 @@ from django.urls import path, include from . import views -urlpatterns = [path("", views.student, name="student"), - path("attendance_student/", views.attendance_student, name="attendance_student"), - path("my_class_student/", views.my_class_student, name="my_class_student"), - path("session_view_student/", views.session_view_student, name="session_view_student")] +urlpatterns = [ + path("", views.student, name="student"), + path("attendance_student/", views.attendance_student, name="attendance_student"), + path("my_class_student/", views.my_class_student, name="my_class_student"), + path( + "session_view_student/", views.session_view_student, name="session_view_student" + ), +] diff --git a/student/views.py b/student/views.py index f56e9f4..08754f5 100644 --- a/student/views.py +++ b/student/views.py @@ -1,11 +1,29 @@ from django.shortcuts import render, redirect from django.contrib.auth.models import Group from home.decorators import group_required -from home.models.models import Announcement, Form, Notification, Attendance, Classroom, Session, Resource -from attendance.views import get_average_attendance_from_list, get_date_from_template_returned_string -from staff.staff_views_helper import get_classroom_by_django_user, get_my_forms, get_my_announcements +from home.models.models import ( + Announcement, + Form, + Notification, + Attendance, + Classroom, + Session, + Resource, +) +from attendance.views import ( + get_average_attendance_from_list, + get_date_from_template_returned_string, +) +from staff.staff_views_helper import ( + get_classroom_by_django_user, + get_my_forms, + get_my_announcements, +) import os -from staff.staff_views_helper import mark_announcement_dismissed, mark_notification_acknowledged +from staff.staff_views_helper import ( + mark_announcement_dismissed, + mark_notification_acknowledged, +) from django.http import HttpResponse, Http404 from datetime import datetime @@ -14,43 +32,73 @@ def student(request): if request.method == "POST": if request.POST.get("dismiss_announcement") == "true": - mark_announcement_dismissed(Announcement.objects.get(id=request.POST.get("announcement")), request.user) + mark_announcement_dismissed( + Announcement.objects.get(id=request.POST.get("announcement")), + request.user, + ) return redirect("student") elif request.POST.get("acknowledge_notification") == "true": - mark_notification_acknowledged(Notification.objects.get(id=request.POST.get("notification"))) + mark_notification_acknowledged( + Notification.objects.get(id=request.POST.get("notification")) + ) return redirect("student") announcements = get_my_announcements(request, "student") forms = get_my_forms(request, "student") - notifications = Notification.objects.filter(user_id=request.user.id, acknowledged=False) - return render(request, "student.html", {"announcements": announcements, - "forms": forms, - "notifications": notifications}) + notifications = Notification.objects.filter( + user_id=request.user.id, acknowledged=False + ) + classroom = get_classroom_by_django_user(request.user) + return render( + request, + "student.html", + { + "announcements": announcements, + "forms": forms, + "notifications": notifications, + "classroom": classroom, + }, + ) @group_required("student") def attendance_student(request): classroom = get_classroom_by_django_user(request.user) - attendance = Attendance.objects.filter(student_id=request.user.id, - date__range=["2000-01-01", datetime.today().date()]).order_by("date") + attendance = Attendance.objects.filter( + student_id=request.user.id, date__range=["2000-01-01", datetime.today().date()] + ).order_by("date") attendance_percentage = get_average_attendance_from_list(attendance) * 100 - return render(request, "attendance_student.html", {"attendance": attendance, - "attendance_percentage": attendance_percentage, - "classroom": classroom}) + return render( + request, + "attendance_student.html", + { + "attendance": attendance, + "attendance_percentage": attendance_percentage, + "classroom": classroom, + }, + ) @group_required("student") def my_class_student(request): classroom = get_classroom_by_django_user(request.user) - sessions = Session.objects.filter(classroom_id=classroom.id, - date__range=["2000-01-01", datetime.today().date()]).order_by("date") - return render(request, "my_class_student.html", {"classroom": classroom, - "sessions": sessions}) + sessions = Session.objects.filter( + classroom_id=classroom.id, date__range=["2000-01-01", datetime.today().date()] + ).order_by("date") + return render( + request, "my_class_student.html", {"classroom": classroom, "sessions": sessions} + ) @group_required("student") def session_view_student(request): - session = Session.objects.get(classroom_id=request.GET.get("classroom"), - date=get_date_from_template_returned_string(request.GET.get("session_date"))) + session = Session.objects.get( + classroom_id=request.GET.get("classroom"), + date=get_date_from_template_returned_string(request.GET.get("session_date")), + ) resources = Resource.objects.filter(session_id=session.id) - return render(request, "session_view_student.html", {"session": session, - "resources": resources}) + classroom = get_classroom_by_django_user(request.user) + return render( + request, + "session_view_student.html", + {"session": session, "resources": resources, "classroom": classroom}, + ) diff --git a/teacher/templates/my_class.html b/teacher/templates/my_class.html deleted file mode 100644 index 298095b..0000000 --- a/teacher/templates/my_class.html +++ /dev/null @@ -1,83 +0,0 @@ -{% extends "teacher_base.html" %} - - -{% block content %} - - - - - - -
    -

    My Class


    - {% if sessions %} - - - - - - - - {% for session in sessions %} - - - - - - - {% endfor %} -
    DateTitleDescriptionView Session
    {{ session.date }}{{ session.title }}{{ session.description }} -
    - - - -
    -
    - {% endif %} -
    - -{% endblock content %} diff --git a/teacher/templates/my_class_teacher.html b/teacher/templates/my_class_teacher.html new file mode 100644 index 0000000..d5d9b38 --- /dev/null +++ b/teacher/templates/my_class_teacher.html @@ -0,0 +1,35 @@ +{% extends "base.html" %} + +{% block content %} + +
    +
    +

    {{ classroom.course }}


    + {% if sessions %} + + + + + + + + {% for session in sessions %} + + + + + + + {% endfor %} +
    DateTitleDescriptionView Session
    {{ session.date }}{{ session.title }}{{ session.description }} +
    + + + +
    +
    + {% endif %} +
    +
    + +{% endblock content %} diff --git a/teacher/templates/session_view.html b/teacher/templates/session_view.html deleted file mode 100644 index bf854f2..0000000 --- a/teacher/templates/session_view.html +++ /dev/null @@ -1,108 +0,0 @@ -{% extends "teacher_base.html" %} -{% load crispy_forms_tags %} - -{% block content %} - - - - - - -
    -

    My Class


    - {% if session %} -

    {{ session.title }} - {{ session.date }}


    -
    - - - -
    -
    -

    Description


    -

    {{ session.description }}


    -

    Lesson Plan


    - {% if session.lesson_plan %} - Download Lesson Plan -
    - {% else %} -

    No Lesson Plan Available


    - {% endif %} -

    Lecture


    - {% if session.lecture %} - Download Lecture -
    - {% else %} -

    No Lecture Available


    - {% endif %} -

    Activity


    - {% if session.activity %} - Download Activity -
    - {% else %} -

    No Activity Available


    - {% endif %} -

    Video


    - {% if session.video %} - View Session Video
    - {% else %} -

    No Video Available


    - {% endif %} -

    Resources


    - {% if resources %} - {% for resource in resources %} -
    {{ resource.title }}
    - {% if resource.file %} - Download Resource -
    - {% endif %} - {% if resource.link %} - Go To Resource
    - {% endif %} - {% endfor %} - {% else %} -

    No Resources


    - {% endif %} - {% endif %} -

    Add Resource for {{ session.date }}

    -
    - {% csrf_token %} - {{ form|crispy }}
    - - - -
    - -
    - -{% endblock content %} diff --git a/teacher/templates/session_view_teacher.html b/teacher/templates/session_view_teacher.html new file mode 100644 index 0000000..fa88bd8 --- /dev/null +++ b/teacher/templates/session_view_teacher.html @@ -0,0 +1,92 @@ +{% extends "base.html" %} +{% load crispy_forms_tags %} + +{% block content %} + +
    +
    +

    {{ classroom.course }} - {{ session.date }}


    + {% if session %} +

    {{ session.title }}

    + Take Attendance +
    +

    Description


    +

    {{ session.description }}


    +

    Lesson Plan


    + {% if session.lesson_plan %} + Download Lesson Plan +
    + {% else %} +

    No Lesson Plan Available


    + {% endif %} +

    Lecture


    + {% if session.lecture %} + Download Lecture +
    + {% else %} +

    No Lecture Available


    + {% endif %} +

    Activity


    + {% if session.activity %} + Download Activity +
    + {% else %} +

    No Activity Available


    + {% endif %} +

    Video


    + {% if session.video %} + View Session Video
    + {% else %} +

    No Video Available


    + {% endif %} +

    Resources


    + {% if resources %} + {% for resource in resources %} +
    {{ resource.title }}
    + {% if resource.file %} + Download Resource +
    + {% endif %} + {% if resource.link %} + Go To Resource
    + {% endif %} + {% endfor %} + {% else %} +

    No Resources


    + {% endif %} + {% endif %} +
    +
    + +
    +
    + {% include "error.html" %} +

    Add Resource for {{ session.date }}

    +
    + {% csrf_token %} +
    + {{ form.title }} + +
    +
    + {{ form.description }} + +
    +
    + {{ form.link }} + +
    +
    + {{ form.file }} + +
    + + + +
    +
    +
    + + +{% endblock content %} diff --git a/teacher/templates/teacher.html b/teacher/templates/teacher.html index 6a52f56..45288e3 100644 --- a/teacher/templates/teacher.html +++ b/teacher/templates/teacher.html @@ -1,98 +1,19 @@ -{% extends "teacher_base.html" %} +{% extends "base.html" %} {% block content %} - - - - -
    -

    Teacher User Home


    +
    + {% include "message.html" %} +

    Teacher User Home


    {% if announcements %} -

    Announcements


    - {% for announcement in announcements reversed %} -
    -

    {{ announcement.title }}


    -

    {{ announcement.announcement }}


    -

    {{ announcement.created_by }} on {{ announcement.posted.date }}


    -
    - {% csrf_token %} - - -

    -
    -

    - {% endfor %} + {% include "announcements.html" %} {% endif %} {% if forms %} -

    Forms


    - {% for form in forms %} -
    -

    {{ form.name }}


    -

    {{ form.description }}


    -

    {{ form.created_by }} on {{ form.posted.date }}


    -

    -

    - -
    -
    -

    -

    - {% endfor %} + {% include "forms.html" %} {% endif %} {% if notifications %} -

    Notifications


    - {% for notification in notifications %} -
    -

    {{ notification.subject }}


    -

    {{ notification.notification }}


    -

    Mission Bit on {{ notification.notified.date }}


    -

    -

    - {% csrf_token %} - - -
    -
    -

    -

    - {% endfor %} + {% include "notifications.html" %} {% endif %} -
    - +
    {% endblock content %} diff --git a/teacher/templates/teacher_base.html b/teacher/templates/teacher_base.html deleted file mode 100644 index 4cd7254..0000000 --- a/teacher/templates/teacher_base.html +++ /dev/null @@ -1,74 +0,0 @@ -{% load static %} - - - - Mission Bit - - - - - - - - - - - - -{% block content %} - - -{% endblock %} - - - - diff --git a/teacher/urls.py b/teacher/urls.py index 0740932..868af1b 100644 --- a/teacher/urls.py +++ b/teacher/urls.py @@ -1,6 +1,10 @@ from django.urls import path, include from . import views -urlpatterns = [path("", views.teacher, name="teacher"), - path("my_class/", views.my_class, name="my_class"), - path("session_view/", views.session_view, name="session_view")] +urlpatterns = [ + path("", views.teacher, name="teacher"), + path("my_class_teacher/", views.my_class_teacher, name="my_class_teacher"), + path( + "session_view_teacher/", views.session_view_teacher, name="session_view_teacher" + ), +] diff --git a/teacher/views.py b/teacher/views.py index f379235..806befb 100644 --- a/teacher/views.py +++ b/teacher/views.py @@ -1,10 +1,22 @@ from django.shortcuts import render, redirect from home.decorators import group_required -from home.models.models import Announcement, Form, Notification, Classroom, Session, Resource +from home.models.models import ( + Announcement, + Form, + Notification, + Classroom, + Session, + Resource, +) from home.forms import AddResourceForm from attendance.views import get_date_from_template_returned_string from staff.staff_views_helper import get_classroom_by_django_user -from staff.staff_views_helper import mark_announcement_dismissed, mark_notification_acknowledged, get_my_announcements, get_my_forms +from staff.staff_views_helper import ( + mark_announcement_dismissed, + mark_notification_acknowledged, + get_my_announcements, + get_my_forms, +) import os from django.http import HttpResponse, Http404 from django.contrib import messages @@ -14,29 +26,43 @@ def teacher(request): if request.method == "POST": if request.POST.get("dismiss_announcement") == "true": - mark_announcement_dismissed(Announcement.objects.get(id=request.POST.get("announcement")), request.user) + mark_announcement_dismissed( + Announcement.objects.get(id=request.POST.get("announcement")), + request.user, + ) return redirect("teacher") elif request.POST.get("acknowledge_notification") == "true": - mark_notification_acknowledged(Notification.objects.get(id=request.POST.get("notification"))) + mark_notification_acknowledged( + Notification.objects.get(id=request.POST.get("notification")) + ) return redirect("teacher") - announcements = get_my_announcements(request, "staff") - forms = get_my_forms(request, "staff") + announcements = get_my_announcements(request, "teacher") + forms = get_my_forms(request, "teacher") notifications = Notification.objects.filter(user_id=request.user.id) - return render(request, "teacher.html", {"announcements": announcements, - "forms": forms, - "notifications": notifications}) + classroom = get_classroom_by_django_user(request.user) + return render( + request, + "teacher.html", + { + "announcements": announcements, + "forms": forms, + "notifications": notifications, + "classroom": classroom, + }, + ) @group_required("teacher") -def my_class(request): +def my_class_teacher(request): classroom = get_classroom_by_django_user(request.user) sessions = Session.objects.filter(classroom_id=classroom.id).order_by("date") - return render(request, "my_class.html", {"sessions": sessions, - "classroom": classroom}) + return render( + request, "my_class_teacher.html", {"sessions": sessions, "classroom": classroom} + ) @group_required("teacher") -def session_view(request): +def session_view_teacher(request): if request.method == "POST": form = AddResourceForm(request.POST, request.FILES) if form.is_valid(): @@ -44,7 +70,7 @@ def session_view(request): title=form.cleaned_data.get("title"), description=form.cleaned_data.get("description"), classroom_id=request.POST.get("classroom"), - session_id=request.POST.get("session") + session_id=request.POST.get("session"), ) if request.POST.get("link"): resource.link = form.cleaned_data.get("link") @@ -53,10 +79,22 @@ def session_view(request): resource.save() messages.add_message(request, messages.SUCCESS, "Resource Added To Session") return redirect("teacher") - session = Session.objects.get(classroom_id=request.GET.get("classroom"), - date=get_date_from_template_returned_string(request.GET.get("session_date"))) + else: + return render(request, "session_view_teacher.html", {"form": form}) + session = Session.objects.get( + classroom_id=request.GET.get("classroom"), + date=get_date_from_template_returned_string(request.GET.get("session_date")), + ) resources = Resource.objects.filter(session_id=session.id) + classroom = get_classroom_by_django_user(request.user) form = AddResourceForm() - return render(request, "session_view.html", {"session": session, - "resources": resources, - "form": form}) + return render( + request, + "session_view_teacher.html", + { + "session": session, + "resources": resources, + "form": form, + "classroom": classroom, + }, + ) diff --git a/tests/test_home.py b/tests/test_home.py index 5380117..6f7753e 100644 --- a/tests/test_home.py +++ b/tests/test_home.py @@ -4,7 +4,7 @@ from django.urls import reverse from rest_framework import status from django.contrib.messages.storage.fallback import FallbackStorage - +from home.forms import ContactRegisterForm, UserRegisterForm from home.views import * @@ -39,7 +39,7 @@ def add_user_to_group(self, user, group): add_to_group = Group.objects.get(name=group) add_to_group.user_set.add(user) - def create_valid_form( + def create_valid_user_and_contact_form( self, username="testuser2", email="test@email.com", @@ -53,6 +53,19 @@ def create_valid_form( "last_name": lastname, "password1": "top_secret_123", "password2": "top_secret_123", + "birthdate": "01/01/1901", + "owner": User.objects.filter(is_active=True).first().id, + "title": "Staff", + "race": "White", + "which_best_describes_your_ethnicity": "Hispanic/Latinx", + "gender": "Female", + } + + def create_valid_contact_form(self): + return { + "first_name": "test_user", + "last_name": "test_user", + "email": "test@email.com", } def create_change_pwd_form(self): @@ -64,6 +77,8 @@ def create_change_pwd_form(self): class HomeViewsTest(BaseTestCase): + databases = "__all__" + def test_home_unauthenticated(self): request = RequestFactory().get(reverse("home-home")) request.user = AnonymousUser() @@ -160,10 +175,6 @@ def test_login(self): response = login(RequestFactory()) self.assertEqual(response.status_code, status.HTTP_302_FOUND) - def test_register(self): - response = self.client.get(reverse("home-register")) - self.assertEqual(response.status_code, status.HTTP_200_OK) - def test_landing_page(self): response = self.client.get(reverse("home-landing_page")) self.assertEqual(response.status_code, status.HTTP_200_OK) @@ -196,12 +207,12 @@ def test_register_after_oauth(self): self.assertEqual(response.status_code, status.HTTP_302_FOUND) def test_register_as_student_post(self): - request = RequestFactory().post(reverse("home-home"), self.create_valid_form()) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - response = register_as_student(request) + self.client.force_login(self.create_user()) + response = self.client.post( + reverse("home-register_as_student"), + self.create_valid_user_and_contact_form(), + ) + Contact.objects.get(client_id="tesuse19010101").delete() self.assertEqual( DjangoUser.objects.filter(first_name="test").first().first_name, "test" ) @@ -209,12 +220,8 @@ def test_register_as_student_post(self): self.assertEqual(response.status_code, status.HTTP_302_FOUND) def test_register_as_student_invalid_form(self): - request = RequestFactory().post(reverse("home-home"), {}) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - response = register_as_student(request) + self.client.force_login(self.create_user()) + response = self.client.post(reverse("home-register_as_student"), {}) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_register_as_volunteer(self): @@ -222,13 +229,12 @@ def test_register_as_volunteer(self): self.assertEqual(response.status_code, status.HTTP_200_OK) def test_register_as_volunteer_post(self): - request = RequestFactory().post(reverse("home-home"), self.create_valid_form()) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - Group.objects.get_or_create(name="volunteer") - response = register_as_volunteer(request) + self.client.force_login(self.create_user()) + response = self.client.post( + reverse("home-register_as_volunteer"), + self.create_valid_user_and_contact_form(), + ) + Contact.objects.get(client_id="tesuse19010101").delete() self.assertEqual( DjangoUser.objects.filter(first_name="test").first().first_name, "test" ) @@ -236,12 +242,8 @@ def test_register_as_volunteer_post(self): self.assertEqual(response.status_code, status.HTTP_302_FOUND) def test_register_as_volunteer_invalid_form(self): - request = RequestFactory().post(reverse("home-home"), {}) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - response = register_as_volunteer(request) + self.client.force_login(self.create_user()) + response = self.client.post(reverse("home-register_as_volunteer"), {}) self.assertEqual(response.status_code, status.HTTP_200_OK) def test_register_as_donor(self): @@ -249,13 +251,11 @@ def test_register_as_donor(self): self.assertEqual(response.status_code, status.HTTP_200_OK) def test_register_as_donor_post(self): - request = RequestFactory().post(reverse("home-home"), self.create_valid_form()) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - Group.objects.get_or_create(name="donor") - response = register_as_donor(request) + self.client.force_login(self.create_user()) + response = self.client.post( + reverse("home-register_as_donor"), self.create_valid_user_and_contact_form() + ) + Contact.objects.get(client_id="tesuse19010101").delete() self.assertEqual( DjangoUser.objects.filter(first_name="test").first().first_name, "test" ) @@ -263,10 +263,6 @@ def test_register_as_donor_post(self): self.assertEqual(response.status_code, status.HTTP_302_FOUND) def test_register_as_donor_invalid_form(self): - request = RequestFactory().post(reverse("home-home"), {}) - request.user = self.create_user() - setattr(request, "session", "session") - messages = FallbackStorage(request) - setattr(request, "_messages", messages) - response = register_as_donor(request) + self.client.force_login(self.create_user()) + response = self.client.post(reverse("home-register_as_donor"), {}) self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/tests/test_staff.py b/tests/test_staff.py index 2c7ed13..6587552 100644 --- a/tests/test_staff.py +++ b/tests/test_staff.py @@ -55,28 +55,18 @@ def setUp(self) -> None: volunteer.userprofile.salesforce_id = "voluse19010101" volunteer.save() Group.objects.get(name="teacher").user_set.add(volunteer) - classroom = Classroom.objects.create( - course="Test_Course" - ) + classroom = Classroom.objects.create(course="Test_Course") ClassroomMembership.objects.create( - member=teacher, - classroom=classroom, - membership_type="teacher" + member=teacher, classroom=classroom, membership_type="teacher" ) ClassroomMembership.objects.create( - member=t_a, - classroom=classroom, - membership_type="teacher_assistant" + member=t_a, classroom=classroom, membership_type="teacher_assistant" ) ClassroomMembership.objects.create( - member=volunteer, - classroom=classroom, - membership_type="volunteer" + member=volunteer, classroom=classroom, membership_type="volunteer" ) ClassroomMembership.objects.create( - member=student, - classroom=classroom, - membership_type="student" + member=student, classroom=classroom, membership_type="student" ) def create_staff_user(self): @@ -130,13 +120,55 @@ def valid_create_class_offering_form(self): def valid_create_classroom_form(self): return { "course": ClassOffering.objects.get(name="Test_Class").id, - "teacher": Contact.objects.get(client_id="clatea19010101").id, - "teacher_assistant": Contact.objects.get(client_id="clatea19010101").id, - "volunteers": Contact.objects.get(client_id="voluse19010101").id, - "students": Contact.objects.get(client_id="stuuse19010101").id, + "teacher": self.get_or_create_test_teacher().id, + "teacher_assistant": self.get_or_create_test_teacher().id, + "volunteers": self.get_or_create_test_volunteer().id, + "students": self.get_or_create_test_student().id, "created_by": User.objects.filter(is_active=True).first().id, } + def get_or_create_test_teacher(self): + contact = Contact.objects.get_or_create( + first_name="classroom", + last_name="teacher", + email="clatea@gmail.com", + birthdate="1901-01-01", + title="Teacher", + owner=User.objects.filter(is_active=True).first(), + race="White", + which_best_describes_your_ethnicity="Hispanic/Latinx", + gender="Female", + ) + return contact[0] + + def get_or_create_test_student(self): + contact = Contact.objects.get_or_create( + first_name="student", + last_name="user", + email="clastu@gmail.com", + birthdate="1901-01-01", + title="Student", + owner=User.objects.filter(is_active=True).first(), + race="White", + which_best_describes_your_ethnicity="Hispanic/Latinx", + gender="Female", + ) + return contact[0] + + def get_or_create_test_volunteer(self): + contact = Contact.objects.get_or_create( + first_name="volunteer", + last_name="user", + email="clavol@gmail.com", + birthdate="1901-01-01", + title="Volunteer", + owner=User.objects.filter(is_active=True).first(), + race="White", + which_best_describes_your_ethnicity="Hispanic/Latinx", + gender="Female", + ) + return contact[0] + def valid_make_announcement_form(self): return { "title": "Test Announcement", @@ -156,22 +188,6 @@ def test_staff(self): self.client.force_login(self.create_nonstaff_user()) self.assertRaises(PermissionError) - def test_user_management(self): - self.client.force_login(self.create_staff_user()) - response = self.client.get(reverse("user_management")) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertTemplateUsed(response, "user_management.html") - self.client.force_login(self.create_nonstaff_user()) - self.assertRaises(PermissionError) - - def test_my_account_staff(self): - self.client.force_login(self.create_staff_user()) - response = self.client.get(reverse("my_account_staff")) - self.assertEqual(response.status_code, status.HTTP_200_OK) - self.assertTemplateUsed(response, "my_account_staff.html") - self.client.force_login(self.create_nonstaff_user()) - self.assertRaises(PermissionError) - def test_classroom_management(self): self.client.force_login(self.create_staff_user()) response = self.client.get(reverse("classroom_management")) @@ -192,8 +208,7 @@ def test_create_classroom(self): def test_create_classroom_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_classroom"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_create_class_offering(self): self.client.force_login(self.create_staff_user()) @@ -209,8 +224,7 @@ def test_create_class_offering(self): def test_create_class_offering_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_class_offering"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_make_announcement(self): self.client.force_login(self.create_staff_user()) @@ -226,8 +240,7 @@ def test_make_announcement(self): def test_make_announcement_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("make_announcement"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_create_staff_user(self): self.client.force_login(self.create_staff_user()) @@ -246,8 +259,7 @@ def test_create_staff_user(self): def test_create_staff_user_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_staff_user"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_create_teacher_user(self): self.client.force_login(self.create_staff_user()) @@ -266,8 +278,7 @@ def test_create_teacher_user(self): def test_create_teacher_user_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_teacher_user"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_create_student_user(self): self.client.force_login(self.create_staff_user()) @@ -286,8 +297,7 @@ def test_create_student_user(self): def test_create_student_user_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_student_user"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) def test_create_volunteer_user(self): self.client.force_login(self.create_staff_user()) @@ -306,5 +316,4 @@ def test_create_volunteer_user(self): def test_create_volunteer_user_invalid_form(self): self.client.force_login(self.create_staff_user()) response = self.client.post(reverse("create_volunteer_user"), {}) - self.assertEqual(response.url, reverse("staff")) - self.assertEqual(response.status_code, status.HTTP_302_FOUND) + self.assertEqual(response.status_code, status.HTTP_200_OK) diff --git a/volunteer/templates/volunteer.html b/volunteer/templates/volunteer.html index 99dc1f0..2e31335 100644 --- a/volunteer/templates/volunteer.html +++ b/volunteer/templates/volunteer.html @@ -1,4 +1,4 @@ -{% extends "home/home.html" %} +{% extends "home_base.html" %} {% block content %}