From a139570222fafb55e9c13c157d520485e80f3227 Mon Sep 17 00:00:00 2001 From: Claude Paroz Date: Thu, 11 Apr 2013 12:45:00 +0200 Subject: [PATCH] Retrieve student list depending on current time and period time If I plan a period for next year, I should obtain the students for the period level minus one. --- stages/models.py | 27 +++++++++++++++++---- stages/tests.py | 29 +++++++++++++++++++---- stages/views.py | 61 +++++++++++++++++++++++++++++------------------- 3 files changed, 83 insertions(+), 34 deletions(-) diff --git a/stages/models.py b/stages/models.py index bd7a790..e6b864f 100644 --- a/stages/models.py +++ b/stages/models.py @@ -1,8 +1,11 @@ # -*- encoding: utf-8 -*- from __future__ import unicode_literals +from datetime import date from django.db import models +from . import utils + def is_int(s): try: @@ -33,6 +36,14 @@ class Level(models.Model): def __unicode__(self): return self.name + def delta(self, diff): + if diff == 0: + return self + try: + return Level.objects.get(name=str(int(self.name)+diff)) + except Level.DoesNotExist: + return None + class Klass(models.Model): name = models.CharField(max_length=10, verbose_name='Nom') @@ -166,11 +177,17 @@ class Period(models.Model): @property def school_year(self): - if self.start_date.month < 8: - start_year = self.start_date.year - 1 - else: - start_year = self.start_date.year - return "%d — %d" % (start_year, start_year + 1) + return utils.school_year(self.start_date) + + @property + def relative_level(self): + """ + Return the level depending on current school year. For example, if the + period is planned for next school year, level will be level - 1. + """ + diff = (utils.school_year(self.start_date, as_tuple=True)[0] - + utils.school_year(date.today(), as_tuple=True)[0]) + return self.level.delta(-diff) @property def weeks(self): diff --git a/stages/tests.py b/stages/tests.py index 5a0b7f6..770daa1 100644 --- a/stages/tests.py +++ b/stages/tests.py @@ -1,11 +1,13 @@ # -*- encoding: utf-8 -*- from __future__ import unicode_literals +from datetime import date from django.contrib.auth.models import User from django.core.urlresolvers import reverse from django.test import TestCase -from .models import Period, Student, Availability, Referent +from .models import Level, Section, Period, Student, Availability, Referent +from .utils import school_year class StagesTest(TestCase): fixtures = ['test_fixture.json'] @@ -33,11 +35,28 @@ class StagesTest(TestCase): avail = Availability.objects.get(pk=2) self.assertEqual(avail.training.student, student) + +class PeriodTest(TestCase): + def setUp(self): + self.section = Section.objects.create(name="ASE") + self.level1 = Level.objects.create(name='1') + self.level2 = Level.objects.create(name='2') + def test_period_schoolyear(self): - per = Period.objects.get(pk=1) + per = Period.objects.create(title="Week test", section=self.section, level=self.level1, + start_date=date(2012, 9, 12), end_date=date(2012, 9, 26)) + self.assertEqual(per.school_year, "2012 — 2013") + per = Period.objects.create(title="Week test", section=self.section, level=self.level1, + start_date=date(2013, 5, 2), end_date=date(2013, 7, 4)) self.assertEqual(per.school_year, "2012 — 2013") - def test_period_weeks(self): - per = Period.objects.get(pk=1) - self.assertEqual(per.weeks, 1) + def test_period_relativelevel(self): + year = school_year(date.today(), as_tuple=True)[1] + per = Period.objects.create(title="For next year", section=self.section, level=self.level2, + start_date=date(year, 9, 12), end_date=date(year, 10, 1)) + self.assertEqual(per.relative_level, self.level1) + def test_period_weeks(self): + per = Period.objects.create(title="Week test", section=self.section, level=self.level1, + start_date=date(2013, 9, 12), end_date=date(2013, 9, 26)) + self.assertEqual(per.weeks, 2) diff --git a/stages/views.py b/stages/views.py index 0c75a0c..28cd65a 100644 --- a/stages/views.py +++ b/stages/views.py @@ -59,6 +59,41 @@ class CorporationView(DetailView): return context +class AttributionView(TemplateView): + """ + Base view for the attribution screen. Populate sections and referents. + All other data are retrieved through AJAX requests: + * training periods: section_period + * corp. availabilities for current period: period_availabilities + * already planned training for current period: TrainingsByPeriodView + * student list targetted by current period: period_students + When an availability is chosen: + * corp. contact list: CorpContactJSONView + When a student is chosen; + * details of a student: StudentSummaryView + """ + template_name = 'attribution.html' + + def get_context_data(self, **kwargs): + context = super(AttributionView, self).get_context_data(**kwargs) + # Need 2 queries, because referents with no training item would not appear in the second query + referents = Referent.objects.all().order_by('last_name', 'first_name') + + # Populate each referent with the number of referencies done during the current school year + ref_counts = dict([(ref.id, ref.num_refs) + for ref in Referent.objects.filter(training__availability__period__end_date__gte=school_year_start + ).annotate(num_refs=Count('training'))]) + for ref in referents: + ref.num_refs = ref_counts.get(ref.id, 0) + + context.update({ + #'period_form': PeriodForm(), + 'sections': Section.objects.all(), + 'referents': referents, + }) + return context + + class StudentSummaryView(DetailView): model = Student template_name = 'student_summary.html' @@ -97,29 +132,6 @@ class CorpContactJSONView(ListView): for obj in context['object_list']] return HttpResponse(json.dumps(serialized), content_type="application/json") - -class AttributionView(TemplateView): - template_name = 'attribution.html' - - def get_context_data(self, **kwargs): - context = super(AttributionView, self).get_context_data(**kwargs) - # Need 2 queries, because referents with no training item would not appear in the second query - referents = Referent.objects.all().order_by('last_name', 'first_name') - - # Populate each referent with the number of referencies done during the current school year - ref_counts = dict([(ref.id, ref.num_refs) - for ref in Referent.objects.filter(training__availability__period__end_date__gte=school_year_start - ).annotate(num_refs=Count('training'))]) - for ref in referents: - ref.num_refs = ref_counts.get(ref.id, 0) - - context.update({ - #'period_form': PeriodForm(), - 'sections': Section.objects.all(), - 'referents': referents, - }) - return context - # AJAX views: def section_periods(request, pk): @@ -141,7 +153,8 @@ def period_students(request, pk): with corresponding Training if existing (JSON) """ period = get_object_or_404(Period, pk=pk) - students = Student.objects.filter(klass__section=period.section, klass__level=period.level).order_by('last_name') + students = Student.objects.filter(klass__section=period.section, klass__level=period.relative_level + ).order_by('last_name') trainings = dict((t.student_id, t.id) for t in Training.objects.filter(availability__period=period)) data = [{ 'name': unicode(s),