Project

General

Profile

« Previous | Next » 

Revision f69ae8a2

Added by Benjamin Dauvergne over 11 years ago

personnes: add views to manage service holidays

View differences:

calebasse/personnes/forms.py
1 1
# -*- coding: utf-8 -*-
2 2
from django import forms
3
from django.forms.models import inlineformset_factory, BaseInlineFormSet
3
from django.forms.models import (inlineformset_factory, modelformset_factory,
4
        BaseInlineFormSet)
4 5
from django.utils.translation import gettext_lazy as _
5 6
from django.contrib.auth.models import User
6 7

  
......
114 115
                'services': forms.CheckboxSelectMultiple,
115 116
        }
116 117

  
118

  
117 119
class BaseTimetableFormSet(BaseInlineFormSet):
118 120
    def __init__(self, weekday=None, *args, **kwargs):
119 121
        kwargs['queryset'] = kwargs.get('queryset', TimeTable.objects).filter(weekday=weekday)
120 122
        super(BaseTimetableFormSet, self).__init__(*args, **kwargs)
121 123

  
124

  
122 125
TimetableFormSet = inlineformset_factory(Worker, TimeTable,
123 126
        formset=BaseTimetableFormSet,
124 127
        fields=('start_time', 'end_time', 'start_date', 'end_date'))
......
126 129
HolidayFormSet = inlineformset_factory(
127 130
        Worker, Holiday,
128 131
        fields=('start_date', 'end_date', 'start_time', 'end_time'))
132

  
133
class HolidaySearchForm(forms.Form):
134
    start_date = forms.DateField(required=False)
135
    end_date = forms.DateField(required=False)
136

  
137
    def clean(self):
138
        cleaned_data = super(HolidaySearchForm, self).clean()
139
        if cleaned_data.get('start_date') or cleaned_data.get('end_date'):
140
            if not cleaned_data.get('start_date') \
141
                   or not cleaned_data.get('end_date'):
142
                raise forms.ValidationError(u'Vous devez fournir une date de début et de fin')
143
            if cleaned_data['start_date'] > cleaned_data['end_date']:
144
                raise forms.ValidationError(u'La date de début doit être supérieure à la date de fin')
145
        return cleaned_data
146

  
147
class YearlyHolidayForm(forms.ModelForm):
148
    for_all_services = forms.BooleanField(required=False)
149

  
150
    def save(self, commit=True):
151
        instance = super(YearlyHolidayForm, self).save(commit=commit)
152
        instance.for_all_services = self.cleaned_data.get('for_all_services', False)
153
        return instance
154

  
155
    class Meta:
156
        form = Holiday
157

  
158
YearlyHolidayFormSet = modelformset_factory(Holiday,
159
        can_delete=True,
160
        form=YearlyHolidayForm,
161
        fields=('start_date', 'end_date'))
calebasse/personnes/templates/personnes/holidays.html
1
{% extends "calebasse/base.html" %}
2

  
3
{% load url from future %}
4

  
5
{% block appbar %}
6
    <h2>Gestion des personnes — Congés</h2>
7
    <a href="..">Retourner à la gestion des personnes</a>
8
{% endblock %}
9

  
10
{% block content %}
11
<h3>Congés du personnel</h3>
12

  
13
{% if current_holidays %}
14
  <h4>En cours</h4>
15

  
16
  <ul>
17
    {% for holiday in current_holidays %}
18
    <li><a href="{% url 'worker_update' service=service pk=holiday.worker.pk %}">
19
        {{ holiday.worker.last_name }} {{holiday.worker.first_name }}
20
        </a>, {{ holiday }}</li>
21
    {% endfor %}
22
  </ul>
23
{% endif %}
24

  
25
{% if future_holidays %}
26
  <h4>À venir</h4>
27

  
28
  <table id="conges-a-venir">
29
    <thead>
30
      <tr>
31
        {% for month in future_holidays %}
32
          <th>{{ month.date|date:"F"|capfirst }}</th>
33
        {% endfor %}
34
      </tr>
35
    </thead>
36
    <tbody>
37
      <tr>
38
        {% for month in future_holidays %}
39
          <td>
40
            <ul>
41
              {% for holiday in month.holidays %}
42
              <li><a href="{% url 'worker_update' service=service pk=holiday.worker.pk %}">
43
                  {{ holiday.worker.last_name }} {{holiday.worker.first_name }}
44
                  </a>, {{ holiday }}</li>
45
              {% endfor %}
46
            </ul>
47
          </td>
48
        {% endfor %}
49
      </tr>
50
    </tbody>
51
  </table>
52
{% endif %}
53

  
54
{% if annual_holidays %}
55
<h3>Congés annuels</h3>
56
<ul>
57
  {% for holiday in annual_holidays %}
58
    <li>{{ holiday|capfirst }}</li>
59
  {% endfor %}
60
</ul>
61
{% endif %}
62
<!-- <button>Gestion des congés annuels</button> -->
63
<p>
64
  <a href="annuel/">Gestion des congés annuels</a>
65
</p>
66

  
67
<h3>Affichage interactif</h3>
68

  
69
  <form>
70
    {{ search_form.non_field_errors }}
71
    {{ search_form.start_date.errors }}
72
    <p>Afficher la liste des congés pris entre
73
      <span id="start-date-datepicker" data-number-of-months="3" data-before-selector="#end-date-datepicker" class="datepicker">{{ search_form.start_date }}</span>
74
      et
75
      <span id="end-date-datepicker" class="datepicker" data-number-of-months="3" data-after-selector="#start-date-datepicker">{{ search_form.end_date }}</span>
76
      <button class="enable-on-change">Valider</button>
77
      <button class="reset">Effacer</button>
78
    </p>
79
  </form>
80
{% endblock %}
calebasse/personnes/templates/personnes/yearly_holiday_update.html
1
{% extends "calebasse/simple-form.html" %}
2

  
3
{% block appbar %}
4
<h2>Congés de {{object.last_name}} {{object.first_name}}</h2>
5
  <a href="..">Retour</a>
6
{% endblock %}
7

  
8

  
9
{% block content %}
10
    <form method="post">
11
      <div id="form-content">
12
        {% csrf_token %}
13
        {% with formset=form %}
14
        {{ formset.management_form }}
15
        <table class="inline">
16
          <thead>
17
            <tr>
18
              <td><label class="required">Date de début</label></td>
19
              <td><label class="required">Date de fin</label></td>
20
              <td><label>Pour tous les services</label></td>
21
              <td><label>Supprimer</label></td>
22
            </tr>
23
          </thead>
24
          <tbody id="timetables">
25
          {% for form in formset %}
26
            {% if form.non_field_errors %}
27
            <tr><td colspan="4">{{ form.non_field_errors }}</td></tr>
28
            {% endif %}
29
            <tr class="timetable">
30
              <td id="start-{{ forloop.counter0 }}" class="datepicker" data-before-selector="#end-{{ forloop.counter0 }}" data-number-of-months="3">{{ form.start_date }}</td>
31
              <td id="end-{{ forloop.counter0 }}" class="datepicker" data-after-selector="#start-{{ forloop.counter0 }}" data-number-of-months="3">{{ form.end_date }}</td>
32
              <td>{{ form.for_all_services }}</td>
33
              <td class="delete">{% if form.id.value != None %}{{ form.DELETE }}{% endif %}
34
                {% for field in form %}
35
                {% if field.is_hidden %}
36
                {{field}}
37
                {% endif %}
38
                {% endfor %}
39
              </td>
40
            </tr>
41
          {% endfor %}
42
          </tbody>
43
        </table>
44
        {% endwith %}
45
      </div>
46
      {% block buttons %}
47
      <button class="enable-on-change">Modifier</button>
48
      <button id="add-form">Ajouter une ligne</button>
49
      {% endblock %}
50
      <a href="..">{% block back-link %}Retour{% endblock %}</a>
51
    </form>
52
{% endblock %}
53

  
54
{% block page-end %}
55
{{ block.super }}
56
<script>
57
  $(function () {
58
    var completions = [];
59
    for (var i = 8*60; i < 21*60; i += 15) {
60
      var completion = ''
61
      var hour = Math.floor(i/60);
62
      var minute = i % 60;
63
      var c = function (v) {
64
        if (v < 10) {
65
          return '0'+v;
66
        }
67
        return v;
68
      }
69
      completions.push(''+c(hour)+':'+c(minute));
70
    }
71
    $('.timepicker input').autocomplete({delay:0, source: completions, minLength: 0});
72
    function addForm() {
73
      var count = $('.timetable').length
74
      var new_row = $('.timetable:first').clone(false).get(0);
75
      $('input', new_row).val('');
76
      $('input, select', new_row).each(function (i, v) {
77
        v.name = v.name.replace('-0-', '-' + count + '-');
78
      });
79
      $('.delete input[type="checkbox"]', new_row).remove();
80
      $('.hasDatepicker', new_row).removeClass('hasDatepicker');
81
      $('*', new_row).each(function (i, v) {
82
        if (v.id) {
83
          v.id = v.id.replace('-0', '-' + count);
84
          if ($(v).data('before-selector')) {
85
            var old_value = $(v).data('before-selector');
86
            $(v).data('before-selector', old_value.replace('-0', '-' + count));
87
          }
88
          if ($(v).data('after-selector')) {
89
            var old_value = $(v).data('after-selector');
90
            $(v).data('after-selector', old_value.replace('-0', '-' + count));
91
          }
92
        }
93
      });
94

  
95
      $(new_row).appendTo($('#timetables'));
96
      $('#id_timetable_set-TOTAL_FORMS').val(count+1);
97
      window.calebasse_dialogs();
98
      return false;
99
    }
100
    $('#add-form').click(addForm);
101
  });
102
</script>
103
{% endblock %}
104

  
105

  
calebasse/personnes/urls.py
12 12
worker_patterns = patterns('calebasse.personnes.views',
13 13
    url(r'^$', 'worker_listing'),
14 14
    url(r'^new/$', 'worker_new'),
15
    url(r'^(?P<pk>\d+)/$', 'worker_update'),
15
    url(r'^(?P<pk>\d+)/$', 'worker_update', name='worker_update'),
16 16
    url(r'^(?P<pk>\d+)/delete/$', 'worker_delete'),
17 17
    url(r'^(?P<pk>\d+)/holidays/$', 'worker_holidays_update'),
18 18
    url(r'^(?P<pk>\d+)/(?P<weekday>\w+)/$', 'worker_schedule_update'),
19 19
)
20 20

  
21
holidays_patterns = patterns('calebasse.personnes.views',
22
    url(r'^$', 'holiday_listing'),
23
    url(r'^annuel/$', 'yearly_holiday_update'))
21 24

  
22 25
urlpatterns = patterns('calebasse.personnes.views',
23 26
    url(r'^$', 'homepage'),
24 27
    url(r'^acces/', include(user_patterns)),
25 28
    url(r'^gestion/', include(worker_patterns)),
29
    url(r'^conges/', include(holidays_patterns)),
26 30
    )
calebasse/personnes/views.py
1 1
from collections import defaultdict
2 2
from datetime import date
3 3

  
4
from dateutil.relativedelta import relativedelta
5

  
4 6
from django.http import HttpResponseRedirect, Http404
5 7
from django.db.models import Q
6 8
from django.contrib.auth.models import User
......
181 183
    success_url = '../'
182 184
    template_name = 'personnes/worker_holidays_update.html'
183 185

  
186
    def get_success_url(self):
187
        return self.success_url
188

  
189

  
184 190
worker_listing = WorkerView.as_view()
185 191
worker_new = cbv.CreateView.as_view(model=models.Worker,
186 192
        template_name='calebasse/simple-form.html',
......
191 197
worker_delete = cbv.DeleteView.as_view(model=models.Worker,
192 198
        template_name='calebasse/simple-form.html',
193 199
        success_url='../')
200

  
201

  
202
class HolidayView(cbv.TemplateView):
203
    months = 3
204
    template_name='personnes/holidays.html'
205

  
206
    def get_form(self):
207
        return forms.HolidaySearchForm(data=self.request.GET)
208

  
209
    def get_context_data(self, **kwargs):
210
        ctx = super(HolidayView, self).get_context_data(**kwargs)
211
        end_date = date.today() + relativedelta(months=self.months)
212
        qs = models.Holiday.objects.for_service_workers(self.service)
213
        today = date.today()
214
        future_qs = qs.filter(start_date__gt=today,
215
                start_date__lte=end_date)
216
        annual_qs = models.Holiday.objects.for_service(self.service)
217
        current_qs = qs.filter(start_date__lte=today)
218
        form = self.get_form()
219
        if form.is_valid() and form.cleaned_data.get('start_date'):
220
            cleaned_data = form.cleaned_data
221
            start_date = cleaned_data['start_date']
222
            end_date = cleaned_data['end_date']
223
            q = Q(start_date__gte=start_date, start_date__lte=end_date)
224
            q |= Q(end_date__gte=start_date, end_date__lte=end_date)
225
            future_qs = models.Holiday.objects.filter(q) \
226
                    .filter(worker__services=self.service)
227
            annual_qs = annual_qs.filter(q)
228
            current_qs = []
229
        ctx['current_holidays'] = current_qs
230
        future_holidays = defaultdict(lambda:[])
231
        for holiday in future_qs:
232
            key = (holiday.start_date.year, holiday.start_date.month, holiday.start_date.strftime('%B'))
233
            future_holidays[key].append(holiday)
234
        ctx['future_holidays'] = [ { 
235
            'date': date(day=1, month=key[1], year=key[0]),
236
            'holidays': future_holidays[key] 
237
          } for key in sorted(future_holidays.keys()) ]
238
        ctx['annual_holidays'] = annual_qs
239
        ctx['search_form'] = form
240
        return ctx
241

  
242

  
243
holiday_listing = HolidayView.as_view()
244

  
245

  
246
class YearlyHolidayUpdateView(cbv.FormView):
247
    form_class = forms.YearlyHolidayFormSet
248
    template_name = 'personnes/yearly_holiday_update.html'
249

  
250
    def get_success_url(self):
251
        return '../'
252

  
253
    def get_form_kwargs(self):
254
        kwargs = super(YearlyHolidayUpdateView, self).get_form_kwargs()
255
        qs = models.Holiday.objects.for_service(self.service)
256
        kwargs['queryset'] = qs
257
        initial = [ { 'for_all_services': o.service is None } for o in qs ]
258
        kwargs['initial'] = initial
259
        return kwargs
260

  
261
    def form_valid(self, form):
262
        instances = form.save(commit=False)
263
        for instance in instances:
264
            if instance.for_all_services:
265
                instance.service = None
266
            else:
267
                instance.service = self.service
268
            instance.save()
269
        return HttpResponseRedirect('')
270

  
271

  
272
yearly_holiday_update = YearlyHolidayUpdateView.as_view()

Also available in: Unified diff