From 5db1c5a33e2be5560cc30b2af36256088bcbabd4 Mon Sep 17 00:00:00 2001 From: Davin Baragiotta Date: Wed, 13 Jun 2012 18:58:41 -0400 Subject: [PATCH] ergo UI : uniformiastion colonnes des changelists --- project/rh/admin.py | 332 +++++++++++--------- project/rh/models.py | 27 ++ .../rh/templates/rh/include/rapports_contrat.html | 5 + .../rh/include/rapports_dossier_poste.html | 8 + project/rh/templates/rh/rapports/base.html | 27 +- project/rh/templates/rh/rapports/contrats.html | 14 +- .../rh/rapports/employes_sans_contrat.html | 48 ++- project/rh/views.py | 119 +++---- project/settings.py | 3 +- 9 files changed, 335 insertions(+), 248 deletions(-) create mode 100644 project/rh/templates/rh/include/rapports_contrat.html create mode 100644 project/rh/templates/rh/include/rapports_dossier_poste.html diff --git a/project/rh/admin.py b/project/rh/admin.py index df95a20..744306e 100644 --- a/project/rh/admin.py +++ b/project/rh/admin.py @@ -7,6 +7,7 @@ from django.contrib import admin from django.conf import settings from django.db.models import Q, Count from django.template.defaultfilters import date +from django.utils.formats import date_format from ajax_select import make_ajax_form @@ -330,12 +331,13 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, '_id', '_apercu', '_nom', - '_poste', '_employe', + '_poste', + '_region', + '_implantation', '_date_debut', '_date_fin', '_date_modification', - 'user_modification', '_dae', ) list_display_links = ('_nom',) @@ -396,14 +398,6 @@ class DossierAdmin(DateRangeMixin, AUFMetadataAdminMixin, _id.short_description = u"#" _id.admin_order_field = "id" - def _nom(self, obj): - return "%d : %s %s" % ( - obj.date_debut.year, - obj.employe.nom.upper(), - obj.employe.prenom) - _nom.allow_tags = True - _nom.short_description = u"Dossier" - def _apercu(self, d): apercu_link = u""" 0: - dossier_dae = dossiers_dae[0] - apercu_link = u""" - - """ % \ - (reverse('embauche_consulter', args=(dossier_dae.id,)), - settings.STATIC_URL, - ) - return apercu_link - _dae.allow_tags = True - _dae.short_description = u"DAE" - - def _date_debut(self, obj): - return date(obj.date_debut) - - _date_debut.short_description = u'Occupation début' - _date_debut.admin_order_field = 'date_debut' + def _nom(self, obj): + return "Dossier" + _nom.allow_tags = True + _nom.short_description = u"Dossier" - def _date_fin(self, obj): - return date(obj.date_fin) - _date_fin.short_description = u'Occupation fin' - _date_fin.admin_order_field = 'date_fin' + def _employe(self, obj): + employe = obj.employe + view_link = reverse('employe_apercu', args=(employe.id,)) + edit_link = reverse('admin:rh_employe_change', args=(employe.id,)) - def _date_modification(self, obj): - return date(obj.date_modification) \ - if obj.date_modification is not None else "(aucune)" - _date_modification.short_description = u'date modification' - _date_modification.admin_order_field = 'date_modification' + style = "" + view = u""" + + """ % (view_link, settings.STATIC_URL,) + return u"""%s%s""" % \ + (view, edit_link, style, employe) + _employe.allow_tags = True + _employe.short_description = u"Employé" + _employe.admin_order_field = "employe__nom" def _poste(self, dossier): link = u""" - %s""" % \ + %s [%d]""" % \ (reverse('poste_apercu', args=(dossier.poste.id,)), settings.STATIC_URL, reverse('admin:rh_poste_change', args=(dossier.poste.id,)), - dossier.poste, + dossier.poste.nom, + dossier.poste.id, ) return link _poste.allow_tags = True _poste.short_description = u'Poste' _poste.admin_order_field = 'poste__nom' - def _employe(self, obj): - employe = obj.employe - view_link = reverse('employe_apercu', args=(employe.id,)) - edit_link = reverse('admin:rh_employe_change', args=(employe.id,)) + def _region(self, obj): + return obj.poste.implantation.region.code + _region.short_description = u"Région" + _region.admin_order_field = 'poste__implantation__region__code' - style = "" - view = u""" - - """ % (view_link, settings.STATIC_URL,) - return u"""%s%s""" % \ - (view, edit_link, style, employe) - _employe.allow_tags = True - _employe.short_description = u"Employé" - _employe.admin_order_field = "employe__nom" + def _implantation(self, obj): + return obj.poste.implantation.nom + _implantation.short_description = u"Implantation" + _implantation.admin_order_field = 'poste__implantation__nom' + + def _date_debut(self, obj): + return date(obj.date_debut) + + _date_debut.short_description = u'Début' + _date_debut.admin_order_field = 'date_debut' + + def _date_fin(self, obj): + return date(obj.date_fin) + _date_fin.short_description = u'Fin' + _date_fin.admin_order_field = 'date_fin' + + def _date_modification(self, obj): + return date(obj.date_modification) \ + if obj.date_modification is not None else "(aucune)" + _date_modification.short_description = u'date modification' + _date_modification.admin_order_field = 'date_modification' + + def _dae(self, d): + apercu_link = "" + dossiers_dae = d.dossiers_dae.all() + if len(dossiers_dae) > 0: + dossier_dae = dossiers_dae[0] + apercu_link = u""" + + """ % \ + (reverse('embauche_consulter', args=(dossier_dae.id,)), + settings.STATIC_URL, + ) + return apercu_link + _dae.allow_tags = True + _dae.short_description = u"DAE" def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) @@ -510,9 +520,10 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, '_apercu', '_nom', '_dossiers_postes', + '_region', + '_implantation', 'date_entree', '_date_modification', - 'user_modification', ) list_display_links = ('_nom',) list_filter = ( @@ -547,6 +558,11 @@ class EmployeAdmin(DateRangeMixin, AUFMetadataAdminMixin, ), ) + def _id(self, obj): + return obj.id + _id.short_description = u"#" + _id.admin_order_field = "id" + def _apercu(self, obj): return u""" - Dossier + Dossier  """ % \ (reverse('dossier_apercu', args=(d.id,)), settings.STATIC_URL, - reverse('admin:rh_dossier_change', args=(d.id,))) + reverse('admin:rh_dossier_change', args=(d.id,)), + link_style,) poste = u""" - Poste + %s [%d]  """ % \ (reverse('poste_apercu', args=(d.poste.id,)), settings.STATIC_URL, - reverse('admin:rh_poste_change', args=(d.poste.id,))) - link = u"""
  • %s %s - %s : [%s] %s
  • """ % \ - (dossier, poste, - d.date_debut.year, - d.poste.id, + reverse('admin:rh_poste_change', args=(d.poste.id,)), + link_style, d.poste.nom, - ) - - # Dossier terminé en gris non cliquable - if d.date_fin is not None and d.date_fin < datetime.date.today(): - link = u"""
  • %s : [%s] %s
  • """ % \ - (d.date_debut.year, - d.poste.id, - d.poste.nom, - ) + d.poste.id) + + link = u"""%s %s""" % \ + (list_style, dossier, poste) l.append(link) return "" % "\n".join(l) _dossiers_postes.allow_tags = True _dossiers_postes.short_description = u"Dossiers et postes" + def _date_modification(self, obj): + return date(obj.date_modification) \ + if obj.date_modification is not None else "(aucune)" + _date_modification.short_description = u'date modification' + _date_modification.admin_order_field = 'date_modification' + def queryset(self, request): qs = super(EmployeAdmin, self).queryset(request) return qs.select_related(depth=1).order_by('nom') @@ -737,13 +767,13 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, '_apercu', '_nom', '_occupe_par', + '_region', '_implantation', '_service', '_responsable', - 'date_debut', - 'date_fin', + '_date_debut', + '_date_fin', '_date_modification', - 'user_modification', '_dae', ) list_filter = ( @@ -819,6 +849,11 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, 'service__isnull', 'vacant__exact', 'vacant__isnull', ) or super(PosteAdmin, self).lookup_allowed(key, value) + def _id(self, obj): + return "%s" % obj.id + _id.short_description = '#' + _id.admin_order_field = 'id' + def _apercu(self, poste): view_link = u""" 0: - poste_dae = postes_dae[0] - apercu_link = \ - u'' \ - u'' % (reverse( - 'poste_consulter', args=("dae-%s" % poste_dae.id,) - ), settings.STATIC_URL) - return apercu_link - _dae.allow_tags = True - _dae.short_description = u"DAE" + def _nom(self, poste): + return """%s""" % \ + (reverse('admin:rh_poste_change', args=(poste.id,)), + poste.nom) + _nom.allow_tags = True + _nom.short_description = u'Poste' + _nom.admin_order_field = 'nom' - def _id(self, obj): - return "%s" % obj.id - _id.short_description = '#' - _id.admin_order_field = 'id' + def _occupe_par(self, obj): + """Formatte la méthode Poste.occupe_par() pour l'admin""" + output = u"Vacant" + if obj.date_fin is not None and obj.date_fin < datetime.date.today(): + return u"s/o" + employes = obj.occupe_par() + if employes: + l = [] + for e in employes: + link = u""" + + + %s""" % \ + (reverse('employe_apercu', args=(e.id,)), + settings.STATIC_URL, + reverse('admin:rh_employe_change', args=(e.id,)), + e) + l.append(link) + output = "\n
    ".join(l) + return output + _occupe_par.allow_tags = True + _occupe_par.short_description = "Occupé par" + + def _region(self, poste): + return poste.implantation.region.code + _region.short_description = 'Région' + _region.admin_order_field = 'implantation__region__code' + + def _implantation(self, poste): + return poste.implantation.nom + _implantation.short_description = 'Implantation' + _implantation.admin_order_field = 'implantation' def _service(self, obj): if obj.service.supprime: @@ -866,12 +924,13 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, - %s + %s [%d]
    """ % \ (reverse('poste_apercu', args=(obj.responsable.id,)), settings.STATIC_URL, reverse('admin:rh_poste_change', args=(obj.responsable.id,)), - obj.responsable.nom) + obj.responsable.nom, + obj.responsable.id) except: responsable = '' @@ -896,48 +955,35 @@ class PosteAdmin(DateRangeMixin, AUFMetadataAdminMixin, _responsable.short_description = 'Responsable' _responsable.allow_tags = True - def _implantation(self, poste): - return poste.implantation.nom - _implantation.short_description = 'Implantation' - _implantation.admin_order_field = 'implantation' + def _date_debut(self, obj): + return date_format(obj.date_debut) + _date_debut.short_description = u'Début' + _date_debut.admin_order_field = 'date_debut' - def _nom(self, poste): - return """%s""" % \ - (reverse('admin:rh_poste_change', args=(poste.id,)), - poste.nom) - _nom.allow_tags = True - _nom.short_description = u'Poste' - _nom.admin_order_field = 'nom' + def _date_fin(self, obj): + return date_format(obj.date_fin) + _date_fin.short_description = u'Fin' + _date_fin.admin_order_field = 'date_fin' def _date_modification(self, obj): return date(obj.date_modification) _date_modification.short_description = u'date modification' _date_modification.admin_order_field = 'date_modification' - def _occupe_par(self, obj): - """Formatte la méthode Poste.occupe_par() pour l'admin""" - output = u"Vacant" - if obj.date_fin is not None and obj.date_fin < datetime.date.today(): - return u"s/o" - employes = obj.occupe_par() - if employes: - l = [] - for e in employes: - link = u""" - - - %s""" % \ - (reverse('employe_apercu', args=(e.id,)), - settings.STATIC_URL, - reverse('admin:rh_employe_change', args=(e.id,)), - e) - l.append(link) - output = "\n
    ".join(l) - return output - _occupe_par.allow_tags = True - _occupe_par.short_description = "Occupé par" + def _dae(self, poste): + apercu_link = "" + postes_dae = poste.postes_dae.all() + if len(postes_dae) > 0: + poste_dae = postes_dae[0] + apercu_link = \ + u'' \ + u'' % (reverse( + 'poste_consulter', args=("dae-%s" % poste_dae.id,) + ), settings.STATIC_URL) + return apercu_link + _dae.allow_tags = True + _dae.short_description = u"DAE" def save_formset(self, request, form, formset, change): instances = formset.save(commit=False) diff --git a/project/rh/models.py b/project/rh/models.py index f39e795..26f8644 100644 --- a/project/rh/models.py +++ b/project/rh/models.py @@ -548,6 +548,16 @@ class Employe(AUFMetadata): q = search.get_q_temporel(self.rh_dossiers) return self.rh_dossiers.filter(q) + def dossier_principal(self): + """Retourne le dossier principal + (ou le plus ancien si il y en a plusieurs) + """ + try: + dossier = self.rh_dossiers.filter(principal=True).order_by('date_debut')[0] + except IndexError, Dossier.DoesNotExist: + dossier = None + return dossier + def postes_encours(self): postes_encours = set() for d in self.dossiers_encours(): @@ -560,6 +570,7 @@ class Employe(AUFMetadata): Idée derrière : si on ajout d'autre Dossiers, c'est pour des Postes secondaires. """ + # DEPRECATED : on a maintenant Dossier.principal poste = Poste.objects.none() try: poste = self.dossiers_encours().order_by('date_debut')[0].poste @@ -951,6 +962,22 @@ class Dossier_(AUFMetadata, DevisableMixin): total += r.montant_euros() return total + def premier_contrat(self): + """contrat avec plus petite date de début""" + try: + contrat = self.rh_contrats.exclude(date_debut=None).order_by('date_debut')[0] + except IndexError, Contrat.DoesNotExist: + contrat = None + return contrat + + def dernier_contrat(self): + """contrat avec plus grande date de fin""" + try: + contrat = self.rh_contrats.exclude(date_debut=None).order_by('-date_debut')[0] + except IndexError, Contrat.DoesNotExist: + contrat = None + return contrat + def actif(self): today = date.today() return (self.date_debut is None or self.date_debut <= today) \ diff --git a/project/rh/templates/rh/include/rapports_contrat.html b/project/rh/templates/rh/include/rapports_contrat.html new file mode 100644 index 0000000..dd94b01 --- /dev/null +++ b/project/rh/templates/rh/include/rapports_contrat.html @@ -0,0 +1,5 @@ +{% if contrat.fichier %} + {{ contrat.type_contrat.nom }} +{% else %} + {{ contrat.type_contrat.nom }} +{% endif %} diff --git a/project/rh/templates/rh/include/rapports_dossier_poste.html b/project/rh/templates/rh/include/rapports_dossier_poste.html new file mode 100644 index 0000000..1171f08 --- /dev/null +++ b/project/rh/templates/rh/include/rapports_dossier_poste.html @@ -0,0 +1,8 @@ + + +  +Dossier : +{{ d.poste.nom }} [{{ d.poste.id }}] diff --git a/project/rh/templates/rh/rapports/base.html b/project/rh/templates/rh/rapports/base.html index 3220eb8..294e268 100644 --- a/project/rh/templates/rh/rapports/base.html +++ b/project/rh/templates/rh/rapports/base.html @@ -2,22 +2,27 @@ {% load adminmedia rapports i18n %} {% block extrastyle %} -{{ block.super }} - + {{ block.super }} + {% endblock %} {% block bodyclass %}change-list{% endblock %} -{% block breadcrumbs %}{% if not is_popup %} - +{% endif %} +{% endblock %} + {% block content %} -{% block count_elements %}{% endblock %} -
    - {% block contentrapport %}{% endblock %} -
    + {% block count_elements %}{% endblock %} +
    +
    + {% block contentrapport %}{% endblock %} +
    +
    {% endblock %} diff --git a/project/rh/templates/rh/rapports/contrats.html b/project/rh/templates/rh/rapports/contrats.html index e897205..e0d2b19 100644 --- a/project/rh/templates/rh/rapports/contrats.html +++ b/project/rh/templates/rh/rapports/contrats.html @@ -9,6 +9,7 @@ {% block extrahead %} + {{ block.super }} {% endblock %} @@ -46,17 +47,12 @@ {{ contrat.dossier.employe.nom|upper }} {{ contrat.dossier.employe.prenom|title }} - - Dossier - - : {{ contrat.dossier.poste.nom }} + {% with contrat.dossier as d %} + {% include 'rh/include/rapports_dossier_poste.html' %} + {% endwith %} - {% if contrat.fichier %} - {{ contrat.type_contrat.nom }} - {% else %} - {{ contrat.type_contrat.nom }} - {% endif %} + {% include 'rh/include/rapports_contrat.html' %} {{ contrat.date_debut }} {{ contrat.date_fin|default:'' }} diff --git a/project/rh/templates/rh/rapports/employes_sans_contrat.html b/project/rh/templates/rh/rapports/employes_sans_contrat.html index c1b9bbb..ea5c28d 100644 --- a/project/rh/templates/rh/rapports/employes_sans_contrat.html +++ b/project/rh/templates/rh/rapports/employes_sans_contrat.html @@ -2,15 +2,16 @@ {% load adminmedia rapports i18n change_list %} {% block extrastyle %} - - -{{ block.super }} + + + + {{ block.super }} {% endblock %} {% block nomrapport %}Rapport Contrats{% endblock %} {% block count_elements %} -

    {{ employes.count }} employés sans contrat

    +

    {{ employes }} employés sans contrat ou contrat échu

    {% endblock %} {% block contentrapport %} @@ -25,35 +26,22 @@ {% table_header headers %} - {% spaceless %} - {% for e in employes %} + {% spaceless %} + {% for d in dossiers %} - {{ e.id }} - {{ e.nom|upper }} {{ e.prenom }} + {{ d.employe.id }} + {{ d.employe.nom|upper }} {{ d.employe.prenom }} + {% include 'rh/include/rapports_dossier_poste.html' %} - {% for d in e.rh_dossiers.all %} - {% if d in dossiers_sans_contrat %} - Dossier : {{ d.poste.nom }} - {% if not forloop.last %}
    {% endif %} - {% endif %} - {% endfor %} - - - {% for d in e.rh_dossiers.all %} - {% if d in dossiers_sans_contrat %} - {{ d.date_debut|default_if_none:"" }} - {% if not forloop.last %}
    {% endif %} - {% endif %} - {% endfor %} - - - {% for d in e.rh_dossiers.all %} - {% if d in dossiers_sans_contrat %} - {{ d.date_fin|default_if_none:"" }} - {% if not forloop.last %}
    {% endif %} - {% endif %} - {% endfor %} + {% with d.dernier_contrat as contrat %} + {% include 'rh/include/rapports_contrat.html' %} + {% endwith %} + {{ d.dernier_contrat.date_debut|default_if_none:"" }} + {{ d.dernier_contrat.date_fin|default_if_none:"" }} + {{ d.get_statut_residence_display }} + {{ d.poste.implantation.region.code }} + {{ d.poste.implantation.nom }} {% endfor %} {% endspaceless %} diff --git a/project/rh/views.py b/project/rh/views.py index eb9bde6..f778732 100644 --- a/project/rh/views.py +++ b/project/rh/views.py @@ -135,6 +135,72 @@ def rapports_contrat(request): @login_required @drh_or_admin_required +def rapports_employes_sans_contrat(request): + """ + Employé sans contrat = a un Dossier qui n'a pas de Contrat associé + Employé avec contrat échu = a un Dossier avec un Contrat se terminant hier + au plus tard... (aujourd'hui = ok, pas date de fin = illimité donc ok) + """ + lookup_params = get_lookup_params(request) + + # contrats échus + contrats_echus = rh.Contrat.objects.filter( + date_fin__lt=date.today() + ).filter( + **lookup_params + ) + + # dossiers en cours sans contrat ou contrats échus + dossiers = rh.Dossier.objects.filter( + Q(date_debut=None) | Q(date_debut__lte=date.today()), + ).filter( + Q(date_fin=None) | Q(date_fin__gte=date.today()), + ).exclude( + date_debut__gt=date.today() + ).filter( + # sans contrat | contrat échu + Q(rh_contrats=None) | Q(rh_contrats__in=contrats_echus) + ).distinct() + + # employés sans contrat ou contrats échus + employes = rh.Employe.objects.filter(rh_dossiers__in=dossiers) \ + .distinct().count() + + # tri + if 'o' in request.GET: + dossiers = dossiers.order_by( + ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o'] + ) + + # affichage + headers = [ + ("employe__id", u"#"), + ("employe__nom", u"Employé"), + ("dossier", u"Dossier : Poste"), + ("rh_contrats__type_contrat", u"Contrat"), + ("rh_contrats__date_debut", u"Début contrat"), + ("rh_contrats__date_fin", u"Fin contrat"), + ("statut_residence", u"Statut"), + ("poste__implantation__region__code", u"Région"), + ("poste__implantation__nom", u"Implantation"), + ] + h = SortHeaders( + request, headers, order_field_type="ot", order_field="o", + not_sortable=('dossier',) + ) + + c = { + 'title': u'Rapport des employés sans contrat ou contrat échu', + 'employes': employes, + 'dossiers': dossiers, + 'headers': list(h.headers()), + } + + return render(request, 'rh/rapports/employes_sans_contrat.html', c) + + +@login_required +@drh_or_admin_required def rapports_masse_salariale(request): class RechercheTemporelle(forms.Form): @@ -244,59 +310,6 @@ def rapports_masse_salariale(request): @login_required @drh_or_admin_required -def rapports_employes_sans_contrat(request): - lookup_params = get_lookup_params(request) - - # contrats échus - contrats_echus = rh.Contrat.objects.filter( - date_fin__lt=date.today() - ).filter( - **lookup_params - ) - - # dossiers en cours sans contrat - dossiers_sans_contrat = rh.Dossier.objects.filter( - Q(date_fin=None) | Q(date_fin__gt=date.today()), - ).exclude( - date_debut__gt=date.today() - ).filter( - rh_contrats__in=contrats_echus - ) - - # employés sans contrat - employes = rh.Employe.objects.filter( - rh_dossiers__in=dossiers_sans_contrat - ).distinct() - if 'o' in request.GET: - employes = employes.order_by( - ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o'] - ) - - # affichage - headers = [ - ("id", u"#"), - ("nom", u"Employé"), - ("dossier", u"Dossier : Poste"), - ("dossier_date_debut", u"Début dossier"), - ("dossier_date_fin", u"Fin dossier"), - ] - h = SortHeaders( - request, headers, order_field_type="ot", order_field="o", - not_sortable=('dossier','dossier_date_debut','dossier_date_fin',) - ) - - c = { - 'title': u'Rapport des employés sans contrat', - 'employes': employes, - 'dossiers_sans_contrat':dossiers_sans_contrat, - 'headers': list(h.headers()), - } - - return render(request, 'rh/rapports/employes_sans_contrat.html', c) - - -@login_required -@drh_or_admin_required def rapports_postes_modelisation(request): c = {} data = [] diff --git a/project/settings.py b/project/settings.py index 5d2527f..4181f8f 100644 --- a/project/settings.py +++ b/project/settings.py @@ -19,13 +19,12 @@ TIME_ZONE = 'America/Montreal' DATE_FORMAT = 'd-m-Y' DATE_INPUT_FORMATS = ( '%d-%m-%Y', '%d/%m/%Y', '%d %m %Y', - '%d-%m-%y', '%d/%m/%y', '%d %m %y', ) +SHORT_DATE_FORMAT = 'd-m-Y' SESSION_SAVE_EVERY_REQUEST = True SESSION_EXPIRE_AT_BROWSER_CLOSE = True -SHORT_DATE_FORMAT = 'd-m-Y' LANGUAGE_CODE = 'fr-ca' # Absolute path to the directory that holds media. -- 1.7.10.4