Rapports: trie des rapports en WIP
[auf_rh_dae.git] / project / rh / templatetags / rapports.py
CommitLineData
fd009814
PP
1# -*- coding: utf-8 -*-
2
72ac5e55
PP
3import datetime
4
fd009814
PP
5from django.utils.encoding import smart_unicode
6from django.template import Library
7from django.utils.http import urlencode
8
9from datamaster_modeles.models import Implantation, Region
23e749e1 10from rh.models import TypeContrat
fd009814
PP
11
12
13register = Library()
14
15
549830eb 16COMBLE_CHOICES = (('c', 'Comblé'), ('n', 'Vacant'))
7821915f
PP
17
18
19@register.inclusion_tag('admin/filter.html', takes_context=True)
20def filter_comble(context):
21 return {'title': 'comblé',
22 'choices': prepare_choices(COMBLE_CHOICES, 'comble', context)}
23
24
fd009814
PP
25@register.inclusion_tag('admin/filter_select.html', takes_context=True)
26def filter_region(context):
27 return {'title': u"région",
28 'choices': prepare_choices(Region.objects.values_list('id', 'nom'), 'implantation__region', context, remove=['pays', 'nord_sud'])}
29
30
31@register.inclusion_tag('admin/filter_select.html', takes_context=True)
32def filter_implantation(context):
33 return {'title': u"implantation",
34 'choices': prepare_choices(Implantation.objects.values_list('id', 'nom'), 'implantation', context)}
35
36
23e749e1
PP
37@register.inclusion_tag('admin/filter_select.html', takes_context=True)
38def filter_region_contrat(context):
39 return {'title': u"région",
40 'choices': prepare_choices(Region.objects.values_list('id', 'nom'), 'dossier__poste__implantation__region', context, remove=['pays', 'nord_sud'])}
41
42
43@register.inclusion_tag('admin/filter_select.html', takes_context=True)
44def filter_implantation_contrat(context):
45 return {'title': u"implantation",
46 'choices': prepare_choices(Implantation.objects.values_list('id', 'nom'), 'dossier__poste__implantation', context)}
47
48
49@register.inclusion_tag('admin/filter_select.html', takes_context=True)
50def filter_type_contrat(context):
51 return {'title': u"type de contrat",
52 'choices': prepare_choices(TypeContrat.objects.values_list('id', 'nom'), 'type_contrat', context)}
53
72ac5e55
PP
54@register.inclusion_tag('admin/filter_select.html', takes_context=True)
55def filter_echeance_contrat(context):
eb204143
JPC
56 today = datetime.date.today()
57 three_months = today + datetime.timedelta(days=3*30)
58 six_months = today + datetime.timedelta(days=6*30)
59 twelve_months = today + datetime.timedelta(days=12*30)
60
61 field_name = 'date_fin'
72ac5e55 62 return {'title': u"échéance",
eb204143
JPC
63 'choices': prepare_choices_date(field_name, context, links=(
64 ('Tous', {}),
65 ('moins de 3 mois', {'%s__gte' % field_name: today.strftime('%Y-%m-%d'),
66 '%s__lte' % field_name: three_months.strftime('%Y-%m-%d')}),
67 ('3 à 6 mois', {'%s__gte' % field_name: three_months.strftime('%Y-%m-%d'),
68 '%s__lte' % field_name: six_months.strftime('%Y-%m-%d')}),
69 ('6 à 12 mois', {'%s__gte' % field_name: six_months.strftime('%Y-%m-%d'),
70 '%s__lte' % field_name: twelve_months.strftime('%Y-%m-%d')}),
71 )
72 )}
73
74@register.inclusion_tag('admin/filter_select.html', takes_context=True)
75def filter_debut_contrat(context):
76 year = datetime.date.today().timetuple()[0]
77 this_year = datetime.date(year, 1, 1)
78 next_year = datetime.date(year + 1, 1, 1)
79 last_year = datetime.date(year - 1, 12,31)
80
81 field_name = 'date_debut'
82 return {'title': u"date début",
83 'choices': prepare_choices_date(field_name, context, links=(
84 ('Tous', {}),
85 ('anées à venirs', {'%s__gte' % field_name: next_year.strftime('%Y-%m-%d')}),
86 ('cette anneée', {'%s__gte' % field_name: this_year.strftime('%Y-%m-%d'),
87 '%s__lt' % field_name: next_year.strftime('%Y-%m-%d')}),
88 ('ans passés', {'%s__lte' % field_name: last_year.strftime('%Y-%m-%d')}),
89 )
90 )}
91
35beb92c
JPC
92@register.inclusion_tag('admin/filter_select.html', takes_context=True)
93def filter_a_venir(context):
94 today = datetime.date.today()
95 year, month, day = datetime.date.today().timetuple()[:3]
96 mois_prochain = datetime.date(year+((month+1)/13), (month+1)%12, 1)
97 this_month = datetime.date(year, month, 1)
98
99 field_name = 'date_debut'
100 return {'title': u"à venir",
101 'choices': prepare_choices_date(field_name, context, links=(
102 ('Tous', {}),
103 ('à venir', {'%s__gt' % field_name: today.strftime('%Y-%m-%d')}),
104 ('à venir mois prochain', {'%s__gte' % field_name: mois_prochain.strftime('%Y-%m-%d')}),
105 ('à venir ce mois', {'%s__gte' % field_name: this_month.strftime('%Y-%m-%d'),
106 '%s__lt' % field_name: mois_prochain.strftime('%Y-%m-%d')}),
107 )
108 )}
109
110
72ac5e55
PP
111
112
af5073aa
PP
113@register.inclusion_tag('admin/filter_select.html', takes_context=True)
114def filter_region_remun(context):
115 return {'title': u"région",
116 'choices': prepare_choices(Region.objects.values_list('id', 'nom'), 'dossiers__poste__implantation__region', context, remove=['pays', 'nord_sud'])}
117
118
119@register.inclusion_tag('admin/filter_select.html', takes_context=True)
120def filter_implantation_remun(context):
121 return {'title': u"implantation",
122 'choices': prepare_choices(Implantation.objects.values_list('id', 'nom'), 'dossiers__poste__implantation', context)}
123
9d53bc73
JPC
124@register.inclusion_tag('admin/table_header.html', takes_context=True)
125def table_header(context, headers):
126 return {'headers': headers}
af5073aa 127
fd009814
PP
128def get_query_string(request, new_params=None, remove=None):
129 if new_params is None: new_params = {}
130 if remove is None: remove = []
131 p = dict(request.GET.items())
132 for r in remove:
133 for k in p.keys():
134 if k.startswith(r):
135 del p[k]
136 for k, v in new_params.items():
137 if v is None:
138 if k in p:
139 del p[k]
140 else:
141 p[k] = v
142 return '?%s' % urlencode(p)
143
144
145def prepare_choices(choices, query_param, context, remove=[]):
146 request = context['request']
147 query_val = request.GET.get(query_param)
148 result = [{'selected': query_val is None,
149 'query_string': get_query_string(request, {}, [query_param] + remove),
150 'display': 'Tout'}]
151 for k, v in choices:
152 result.append({'selected': smart_unicode(k) == query_val,
153 'query_string': get_query_string(request, {query_param: k}, remove),
154 'display': v})
155 return result
72ac5e55
PP
156
157
eb204143 158def prepare_choices_date(field_name, context, links, remove=[]):
72ac5e55
PP
159 request = context['request']
160 params = request.GET
161 field_generic = '%s__' % field_name
162 date_params = dict([(k, v) for k, v in params.items() if k.startswith(field_generic)])
163
164
eb204143 165
72ac5e55
PP
166 result = []
167 for title, param_dict in links:
168 result.append({'selected': date_params == param_dict,
169 'query_string': get_query_string(request, param_dict, [field_generic]),
170 'display': title})
171 return result
9d53bc73
JPC
172
173ORDER_VAR = 'o'
174ORDER_TYPE_VAR = 'ot'
175
176class SortHeaders:
177 """
178 Handles generation of an argument for the Django ORM's
179 ``order_by`` method and generation of table headers which reflect
180 the currently selected sort, based on defined table headers with
181 matching sort criteria.
182
183 Based in part on the Django Admin application's ``ChangeList``
184 functionality.
185
186 http://djangosnippets.org/snippets/308/
187 """
188 def __init__(self, request, headers, default_order_field=None,
189 default_order_type='asc', additional_params=None):
190 """
191 request
192 The request currently being processed - the current sort
193 order field and type are determined based on GET
194 parameters.
195
196 headers
197 A list of two-tuples of header text and matching ordering
198 criteria for use with the Django ORM's ``order_by``
199 method. A criterion of ``None`` indicates that a header
200 is not sortable.
201
202 default_order_field
203 The index of the header definition to be used for default
204 ordering and when an invalid or non-sortable header is
205 specified in GET parameters. If not specified, the index
206 of the first sortable header will be used.
207
208 default_order_type
209 The default type of ordering used - must be one of
210 ``'asc`` or ``'desc'``.
211
212 additional_params:
213 Query parameters which should always appear in sort links,
214 specified as a dictionary mapping parameter names to
215 values. For example, this might contain the current page
216 number if you're sorting a paginated list of items.
217 """
218 if default_order_field is None:
219 for i, (header, query_lookup) in enumerate(headers):
220 if query_lookup is not None:
221 default_order_field = i
222 break
223 if default_order_field is None:
224 raise AttributeError('No default_order_field was specified and none of the header definitions given were sortable.')
225 if default_order_type not in ('asc', 'desc'):
226 raise AttributeError('If given, default_order_type must be one of \'asc\' or \'desc\'.')
227 if additional_params is None: additional_params = {}
228
229 self.header_defs = headers
230 self.additional_params = additional_params
231 self.order_field, self.order_type = default_order_field, default_order_type
232
233 # Determine order field and order type for the current request
234 params = dict(request.GET.items())
235 if ORDER_VAR in params:
236 try:
237 new_order_field = int(params[ORDER_VAR])
238 if headers[new_order_field][1] is not None:
239 import pdb
240 pdb.set_trace()
241 self.order_field = params[ORDER_VAR]
242 except (IndexError, ValueError):
243 pass # Use the default
244 if ORDER_TYPE_VAR in params and params[ORDER_TYPE_VAR] in ('asc', 'desc'):
245 self.order_type = params[ORDER_TYPE_VAR]
246 try:
247 del params[ORDER_VAR]
248 except KeyError:
249 pass
250 try:
251 del params[ORDER_TYPE_VAR]
252 except KeyError:
253 pass
254 self.additional_params = params
255
256 def headers(self):
257 """
258 Generates dicts containing header and sort link details for
259 all defined headers.
260 """
261 for i, (header, order_criterion) in enumerate(self.header_defs):
262 th_classes = []
263 new_order_type = 'asc'
264 if i == self.order_field:
265 th_classes.append('sorted %sending' % self.order_type)
266 new_order_type = {'asc': 'desc', 'desc': 'asc'}[self.order_type]
267 yield {
268 'text': header,
269 'sortable': order_criterion is not None,
270 'url': self.get_query_string({ORDER_VAR: i, ORDER_TYPE_VAR: new_order_type}),
271 'class_attr': (th_classes and ' '.join(th_classes) or ''),
272 }
273
274 def get_query_string(self, params):
275 """
276 Creates a query string from the given dictionary of
277 parameters, including any additonal parameters which should
278 always be present.
279 """
280 params.update(self.additional_params)
281 if self.order_type == params[ORDER_TYPE_VAR] and self.order_field == params[ORDER_VAR]:
282 params[ORDER_TYPE_VAR] = 'asc' if params[ORDER_TYPE_VAR] == "desc" else "desc"
283 return '?%s' % '&'.join(['%s=%s' % (param, value) \
284 for param, value in params.items()])
285
286 def get_order_by(self):
287 """
288 Creates an ordering criterion based on the current order
289 field and order type, for use with the Django ORM's
290 ``order_by`` method.
291 """
292 return '%s%s' % (
293 self.order_type == 'desc' and '-' or '',
294 self.header_defs[self.order_field][1],
295 )