Commit | Line | Data |
---|---|---|
fd009814 PP |
1 | # -*- coding: utf-8 -*- |
2 | ||
72ac5e55 PP |
3 | import datetime |
4 | ||
fd009814 PP |
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 | |
23e749e1 | 10 | from rh.models import TypeContrat |
fd009814 PP |
11 | |
12 | ||
13 | register = Library() | |
14 | ||
15 | ||
549830eb | 16 | COMBLE_CHOICES = (('c', 'Comblé'), ('n', 'Vacant')) |
7821915f PP |
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 | ||
fd009814 PP |
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 | ||
23e749e1 PP |
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 | ||
72ac5e55 PP |
54 | @register.inclusion_tag('admin/filter_select.html', takes_context=True) |
55 | def 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) | |
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 | ||
35beb92c JPC |
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 | ||
72ac5e55 PP |
111 | |
112 | ||
af5073aa PP |
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 | ||
9d53bc73 JPC |
124 | @register.inclusion_tag('admin/table_header.html', takes_context=True) |
125 | def table_header(context, headers): | |
126 | return {'headers': headers} | |
af5073aa | 127 | |
fd009814 PP |
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 | |
72ac5e55 PP |
156 | |
157 | ||
eb204143 | 158 | def 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 | |
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 | ) |