Rapports: trie des rapports en WIP
[auf_rh_dae.git] / project / rh / templatetags / rapports.py
1 # -*- coding: utf-8 -*-
2
3 import datetime
4
5 from django.utils.encoding import smart_unicode
6 from django.template import Library
7 from django.utils.http import urlencode
8
9 from datamaster_modeles.models import Implantation, Region
10 from rh.models import TypeContrat
11
12
13 register = Library()
14
15
16 COMBLE_CHOICES = (('c', 'Comblé'), ('n', 'Vacant'))
17
18
19 @register.inclusion_tag('admin/filter.html', takes_context=True)
20 def filter_comble(context):
21 return {'title': 'comblé',
22 'choices': prepare_choices(COMBLE_CHOICES, 'comble', context)}
23
24
25 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
26 def 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)
32 def filter_implantation(context):
33 return {'title': u"implantation",
34 'choices': prepare_choices(Implantation.objects.values_list('id', 'nom'), 'implantation', context)}
35
36
37 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
38 def 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)
44 def 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)
50 def 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
54 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
55 def filter_echeance_contrat(context):
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'
62 return {'title': u"échéance",
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)
75 def 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
92 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
93 def 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
111
112
113 @register.inclusion_tag('admin/filter_select.html', takes_context=True)
114 def 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)
120 def filter_implantation_remun(context):
121 return {'title': u"implantation",
122 'choices': prepare_choices(Implantation.objects.values_list('id', 'nom'), 'dossiers__poste__implantation', context)}
123
124 @register.inclusion_tag('admin/table_header.html', takes_context=True)
125 def table_header(context, headers):
126 return {'headers': headers}
127
128 def 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
145 def 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
156
157
158 def prepare_choices_date(field_name, context, links, remove=[]):
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
165
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
172
173 ORDER_VAR = 'o'
174 ORDER_TYPE_VAR = 'ot'
175
176 class 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 )