Skip to content

Commit

Permalink
Merge pull request #55 from defivelo/seasons-are-seasons
Browse files Browse the repository at this point in the history
Transform seasons from begin/end to year/season
  • Loading branch information
OdyX authored Aug 29, 2017
2 parents 527944b + c116411 commit 0c61fc3
Show file tree
Hide file tree
Showing 13 changed files with 599 additions and 456 deletions.
19 changes: 7 additions & 12 deletions apps/challenge/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals

from bootstrap3_datetime.widgets import DateTimePicker
from dal_select2.widgets import ModelSelect2
from django import forms
from django.conf import settings
Expand Down Expand Up @@ -54,17 +55,11 @@ def __init__(self, *args, **kwargs):
)
self.fields['cantons'].choices = choices

def clean_end(self):
begin = self.cleaned_data.get("begin")
end = self.cleaned_data.get("end")
if end <= begin:
raise forms.ValidationError(
_("La fin doit être après le début.")
)
return end

begin = SwissDateField(label=_('Début'))
end = SwissDateField(label=_('Fin'))
year = forms.IntegerField(label=_('Année'),
widget=DateTimePicker(
{'placeholder': 'YYYY'},
options={
"format": 'YYYY'}))
leader = LeaderChoiceField(label=_('Chargé·e de projet'),
queryset=(
get_user_model().objects
Expand All @@ -76,7 +71,7 @@ def clean_end(self):

class Meta:
model = Season
fields = ['begin', 'end', 'cantons', 'leader']
fields = ['year', 'season', 'cantons', 'leader']


class SessionForm(forms.ModelForm):
Expand Down
38 changes: 38 additions & 0 deletions apps/challenge/migrations/0041_seasons_are_seasons.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-29 12:19
from __future__ import unicode_literals

from django.db import migrations, models

from apps.common import DV_SEASON_LAST_SPRING_MONTH

def fill_in_seasons(apps, schema_editor):
# We can't import the Person model directly as it may be a newer
# version than this migration expects. We use the historical version.
Season = apps.get_model('challenge', 'Season')
for season in Season.objects.all():
season.year = season.begin.year
season.season = 1 if season.begin.month <= DV_SEASON_LAST_SPRING_MONTH else 3
season.save()


class Migration(migrations.Migration):

dependencies = [
('challenge', '0040_auto_20170825_1349'),
]

operations = [
migrations.AddField(
model_name='season',
name='season',
field=models.PositiveSmallIntegerField(choices=[(1, 'Printemps'), (3, 'Automne')], default=1, verbose_name='Saison'),
),
migrations.AddField(
model_name='season',
name='year',
field=models.PositiveSmallIntegerField(default=2000, verbose_name='Année'),
preserve_default=False,
),
migrations.RunPython(fill_in_seasons, migrations.RunPython.noop),
]
27 changes: 27 additions & 0 deletions apps/challenge/migrations/0042_auto_20170829_1438.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.11.4 on 2017-08-29 12:38
from __future__ import unicode_literals

from django.db import migrations


class Migration(migrations.Migration):

dependencies = [
('challenge', '0041_seasons_are_seasons'),
]

operations = [
migrations.AlterModelOptions(
name='season',
options={'ordering': ['year', 'season'], 'verbose_name': 'Saison', 'verbose_name_plural': 'Saisons'},
),
migrations.RemoveField(
model_name='season',
name='begin',
),
migrations.RemoveField(
model_name='season',
name='end',
),
]
39 changes: 31 additions & 8 deletions apps/challenge/models/season.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,24 +17,29 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals

from datetime import date

from django.conf import settings
from django.core.urlresolvers import reverse
from django.db import models
from django.template.defaultfilters import date
from django.utils.encoding import python_2_unicode_compatible
from django.utils.translation import ugettext_lazy as _
from multiselectfield import MultiSelectField

from apps.common import DV_STATE_CHOICES
from apps.common import (
DV_SEASON_AUTUMN, DV_SEASON_CHOICES, DV_SEASON_LAST_SPRING_MONTH, DV_SEASON_SPRING, DV_STATE_CHOICES,
)

from .session import Session


@python_2_unicode_compatible
class Season(models.Model):
created_on = models.DateTimeField(auto_now_add=True)
begin = models.DateField(_('Début'))
end = models.DateField(_('Fin'))
year = models.PositiveSmallIntegerField(_('Année'))
season = models.PositiveSmallIntegerField(_('Saison'),
choices=DV_SEASON_CHOICES,
default=DV_SEASON_SPRING)
cantons = MultiSelectField(_('Cantons'), choices=sorted(DV_STATE_CHOICES))
leader = models.ForeignKey(settings.AUTH_USER_MODEL,
verbose_name=_('Chargé de projet'),
Expand All @@ -47,13 +52,31 @@ class Season(models.Model):
class Meta:
verbose_name = _('Saison')
verbose_name_plural = _('Saisons')
ordering = ['begin', 'end', ]
ordering = ['year', 'season', ]

@property
def cantons_verb(self):
if self.cantons:
return [c[1] for c in DV_STATE_CHOICES if c[0] in self.cantons]

@property
def begin(self):
if self.season == DV_SEASON_SPRING:
return date(self.year, 1, 1)
if self.season == DV_SEASON_AUTUMN:
return date(self.year, DV_SEASON_LAST_SPRING_MONTH + 1, 1)

@property
def end(self):
if self.season == DV_SEASON_SPRING:
return date(self.year, DV_SEASON_LAST_SPRING_MONTH + 1, 1)
if self.season == DV_SEASON_AUTUMN:
return date(self.year + 1, 1, 1)

@property
def season_full(self):
return dict(DV_SEASON_CHOICES)[self.season]

@property
def sessions(self):
return Session.objects.filter(
Expand Down Expand Up @@ -86,9 +109,9 @@ def get_absolute_url(self):
return reverse('season-detail', args=[self.pk])

def desc(self):
return _('{cantons} - {depuis_mois} à {jusqu_mois}').format(
depuis_mois=date(self.begin, "F").title(),
jusqu_mois=date(self.end, "F Y"),
return _('{cantons} - {saison} {annee}').format(
saison=self.season_full,
annee=self.year,
cantons=", ".join(self.cantons),
)

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,25 +2,25 @@
{% load i18n %}
{% load bootstrap3 %}
{% load dv_filters %}
{% block head_title %}{% blocktrans with year=year.year %}Saisons {{ year }}{% endblocktrans %}{% endblock %}
{% block head_title %}{% blocktrans with year=year %}Saisons {{ year }}{% endblocktrans %}{% endblock %}

{% block content %}
<h1>{% blocktrans with year=year.year %}Saisons {{ year }}{% endblocktrans %}</h1>
<h1>{% blocktrans with year=year %}Saisons {{ year }}{% endblocktrans %}</h1>

<nav>
<ul class="pager">
<li class="previous btn-xs">
<a href="{% url 'season-list' year=previous_year.year %}">
<span aria-hidden="true">&larr;</span> {{ previous_year.year }}
<a href="{% url 'season-list' year=year|add:"-1" %}">
<span aria-hidden="true">&larr;</span> {{ year|add:"-1" }}
</a>
</li>
{% if year.year != now.year %}
{% if year|add:0 != now.year|add:0 %}
<li class="btn-xs"><a href="{% url 'season-list' year=now.year %}">{% trans "Année courante" %}</a>
</li>
{% endif %}
<li class="next btn-xs">
<a href="{% url 'season-list' year=next_year.year %}">
{{ next_year.year }} <span aria-hidden="true">&rarr;</span>
<a href="{% url 'season-list' year=year|add:"1" %}">
{{ year|add:"1" }} <span aria-hidden="true">&rarr;</span>
</a>
</li>
</ul>
Expand Down
8 changes: 4 additions & 4 deletions apps/challenge/tests/factories.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@
from factory import Faker, fuzzy
from factory.django import DjangoModelFactory

from apps.common import DV_STATES
from apps.common import DV_SEASON_CHOICES, DV_STATES
from apps.orga.tests.factories import OrganizationFactory
from apps.user.tests.factories import UserFactory

Expand All @@ -34,8 +34,8 @@ class SeasonFactory(DjangoModelFactory):
class Meta:
model = Season

begin = fuzzy.FuzzyDate(date(2015, 1, 1), date(2015, 5, 1))
end = fuzzy.FuzzyDate(date(2015, 7, 1), date(2015, 12, 31))
year = fuzzy.FuzzyInteger(1999, 2050)
season = fuzzy.FuzzyChoice([_s[0] for _s in DV_SEASON_CHOICES])
# Juste un canton
cantons = fuzzy.FuzzyChoice(DV_STATES)
leader = factory.SubFactory(UserFactory)
Expand All @@ -46,7 +46,7 @@ class Meta:
model = Session

orga = factory.SubFactory(OrganizationFactory)
day = fuzzy.FuzzyDate(date(2015, 5, 2), date(2015, 6, 30))
day = fuzzy.FuzzyDate(date(1999, 1, 1), date(2050, 1, 1))


class QualificationFactory(DjangoModelFactory):
Expand Down
15 changes: 6 additions & 9 deletions apps/challenge/tests/test_seasons.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
from django.core.urlresolvers import reverse
from django.test import TestCase

from apps.common import DV_STATES
from apps.common import DV_SEASON_SPRING, DV_STATES
from apps.common.forms import SWISS_DATE_INPUT_FORMAT
from apps.orga.tests.factories import OrganizationFactory
from apps.user.models import FORMATION_M1
Expand Down Expand Up @@ -55,10 +55,11 @@ def setUp(self):
self.season.save()

self.sessions = []
for canton in self.mycantons:
for canton in self.season.cantons:
s = SessionFactory()
s.orga.address_canton = canton
s.orga.save()
s.day = self.season.begin
s.save()
for i in range(0, 4):
QualificationFactory(session=s).save()
Expand All @@ -75,6 +76,7 @@ def setUp(self):
s = SessionFactory()
s.orga.address_canton = canton
s.orga.save()
s.day = self.foreignseason.begin
s.save()
for i in range(0, 4):
QualificationFactory(session=s).save()
Expand Down Expand Up @@ -240,8 +242,8 @@ def test_season_creation(self):
self.assertEqual(response.status_code, 200, url)

initial = {
'begin': '09.03.2015',
'end': '10.03.2015',
'year': 2015,
'season': DV_SEASON_SPRING,
'cantons': [],
'leader': self.client.user.pk,
}
Expand All @@ -260,11 +262,6 @@ def test_season_creation(self):
response = self.client.post(url, initial)
self.assertEqual(response.status_code, 302, url)

initial['end'] = '08.03.2015' # Inverse dates
# That must not work
response = self.client.post(url, initial)
self.assertEqual(response.status_code, 200, url)

def test_session_creation(self):
url = reverse('session-create', kwargs={'seasonpk': self.season.pk})
# Final URL is OK
Expand Down
21 changes: 17 additions & 4 deletions apps/challenge/views/season.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import unicode_literals

import datetime
import operator
from collections import OrderedDict
from functools import reduce
Expand All @@ -29,7 +30,7 @@
from django.http import HttpResponseRedirect
from django.template.defaultfilters import date, time
from django.utils.translation import ugettext as u, ugettext_lazy as _
from django.views.generic.dates import YearArchiveView
from django.views.generic import ListView
from django.views.generic.detail import DetailView
from django.views.generic.edit import CreateView, DeleteView, UpdateView
from rolepermissions.mixins import HasPermissionsMixin
Expand Down Expand Up @@ -79,7 +80,7 @@ def get_queryset(self):
if self.model == Season:
return self.request.user.profile.get_seasons(
self.raise_without_cantons
).prefetch_related('leader').order_by('cantons', 'begin')
).prefetch_related('leader').order_by('cantons', 'season')

qs = super(SeasonMixin, self).get_queryset()

Expand All @@ -100,14 +101,26 @@ def get_queryset(self):
return qs


class SeasonListView(SeasonMixin, YearArchiveView):
date_field = 'begin'
class SeasonListView(SeasonMixin, ListView):
allow_empty = True
allow_future = True
context_object_name = 'seasons'
make_object_list = True
raise_without_cantons = False

def get_queryset(self):
self.year = self.kwargs.pop('year', datetime.date.today().year)
return (
super(SeasonListView, self).get_queryset()
.filter(year=self.year)
.order_by('season', 'cantons')
)

def get_context_data(self, **kwargs):
context = super(SeasonListView, self).get_context_data(**kwargs)
context['year'] = self.year
return context


class SeasonDetailView(SeasonMixin, HasPermissionsMixin, DetailView):
def get_context_data(self, **kwargs):
Expand Down
12 changes: 12 additions & 0 deletions apps/common/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -56,3 +56,15 @@
list((('', '---------',),)) +
list(DV_LANGUAGES)
)

DV_SEASON_SPRING = 1
# DV_SEASON_SUMMER = 2
DV_SEASON_AUTUMN = 3
# DV_SEASON_WINTER = 4

DV_SEASON_CHOICES = (
(DV_SEASON_SPRING, _('Printemps')),
(DV_SEASON_AUTUMN, _('Automne')),
)

DV_SEASON_LAST_SPRING_MONTH = 7
2 changes: 1 addition & 1 deletion apps/user/templates/auth/user_detail.html
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ <h2 class="panel-title">
{% endif %}
{% if userprofile.profile.natel %}
<dt>{% trans "Natel" %}</dt>
<dd><a class="tel" href="tel:{{ userprofile.profile.natel|tel_int }}">{{ userprofile.profile.natel }}</a></dd>
<dd>{{ userprofile.profile.natel|tel_link }}</dd>
{% endif %}
</dl>
</div>
Expand Down
2 changes: 1 addition & 1 deletion defivelo/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_context_data(self, **kwargs):
context = super(MenuView, self).get_context_data(**kwargs)
context['current_seasons'] = (
self.request.user.profile.get_seasons()
.filter(end__gte=date.today())
.filter(year=date.today().year)
)
context['now'] = timezone.now()
return context
Expand Down
Loading

0 comments on commit 0c61fc3

Please sign in to comment.