conflit réglé merge master et regionalisation
authorDavin Baragiotta <davin.baragiotta@auf.org>
Tue, 5 Jun 2012 21:46:46 +0000 (17:46 -0400)
committerDavin BARAGIOTTA <davin.baragiotta@auf.org>
Tue, 5 Jun 2012 21:46:46 +0000 (17:46 -0400)
1  2 
project/dae/admin.py
project/decorators.py
project/menu.py
project/recrutement/admin.py
project/rh/admin.py
project/rh/models.py
project/rh/templatetags/rapports.py
project/rh/views.py
project/settings.py
versions.cfg

Simple merge
@@@ -31,5 -23,50 +23,65 @@@ def redirect_interdiction(request, msg=
      tup = login_url, REDIRECT_FIELD_NAME, path
      messages.add_message(request, messages.ERROR, "Votre compte ne permet pas d'accéder à cette partie de l'application.")
      return HttpResponseRedirect('%s?%s=%s' % tup)
+     
+ def in_drh_or_admin(user):
+     """
+     Teste si un user Django fait parti du groupe DRH, DRH2 ou s'il est admin
+     """
+     groups = user.groups.all()
+     if user.is_superuser or \
+             grp_drh in groups or \
+             grp_drh2 in groups:
+         return True
+     else:
+         return False
+         
+ def drh_or_admin_required(fn):
+     """
+     Teste si un user Django fait parti du groupe DRH, DRH2 ou s'il est admin
+     """
+     def inner(request, *args, **kwargs):
+         user = request.user
+         if in_drh_or_admin(user):
+             return fn(request, *args, **kwargs)
  
+         msg = u"Votre compte ne permet pas d'accéder à " \
+                 u"cette partie de l'application."
+         return redirect_interdiction(request, msg)
  
+     return inner
+     
+ def region_protected(model):
+     def wrapper(func):
+         def wrapped(request, id):
+             if request.user.is_superuser:
+                 return func(request, id)
+             user_groups = request.user.groups.all()
+             if grp_drh in user_groups:
+                 return func(request, id)
+             if grp_correspondants_rh in user_groups:
+                 employe = get_employe_from_user(request.user)
+                 q = Q(**{
+                     model.prefix_implantation: employe.implantation.region
+                 })
+                 qs = model.objects.filter(q)
+                 if int(id) in [o.id for o in qs]:
+                     return func(request, id)
+             return redirect_interdiction(request)
+         return wrapped
+     return wrapper
++    
++def in_one_of_group(groups):
++    """
++    Test si le user appartient au moins 1 des ces groupes
++    """
++    def wrapper(fn):
++        def wrapped(request, *args, **kwargs):
++            user_groups = request.user.groups.all()
++            for g in user_groups:
++                if g in groups:
++                    return fn(request, *args, **kwargs)
++            msg = u"Votre compte ne permet pas d'accéder à cette partie de l'application."
++            return redirect_interdiction(request, msg)
++        return wrapped
++    return wrapper
diff --cc project/menu.py
@@@ -12,8 -12,8 +12,10 @@@ from django.core.urlresolvers import re
  from django.utils.translation import ugettext_lazy as _
  
  from admin_tools.menu import items, Menu
- from project.rh.decorators import in_drh_or_admin
- from project.rh import groups
+ from project.decorators import in_drh_or_admin
++from project import groups
++
  
  class CustomMenu(Menu):
      """
Simple merge
@@@ -12,14 -8,21 +8,21 @@@ from django.conf import setting
  from django.db.models import Q, Count
  from django.template.defaultfilters import date
  
+ from ajax_select import make_ajax_form
+ from auf.django.metadata.admin import \
+         AUFMetadataAdminMixin, AUFMetadataInlineAdminMixin, \
+         AUF_METADATA_READONLY_FIELDS
  import auf.django.references.models as ref
- import models as rh
- from forms import \
++from project import groups
+ from project.decorators import in_drh_or_admin
 -from project.groups import grp_correspondants_rh
+ from project.groups import get_employe_from_user
+ import project.rh.models as rh
+ from project.rh.forms import \
          ContratForm, AyantDroitForm, EmployeAdminForm, AjaxSelect, DossierForm
- from dae.utils import get_employe_from_user
- from change_list import ChangeList
- from project.rh import groups
- from decorators import in_drh_or_admin
+ from project.rh.change_list import ChangeList
  
  
  class BaseAdmin(admin.ModelAdmin):
Simple merge
@@@ -6,11 -6,10 +6,12 @@@ from django.utils.encoding import smart
  from django.template import Library
  from django.utils.http import urlencode
  
- from datamaster_modeles.models import Implantation, Region
- from rh.models import TypeContrat
- from project.rh import groups
- # pas de reference a DAE devrait etre refactorisé
- from dae.utils import get_employe_from_user
+ from auf.django.references.models import Implantation, Region
 -from project.rh.models import TypeContrat
++from project import groups
++from project.groups import get_employe_from_user
++from project.rh.models import TypeContrat
  
  register = Library()
  
@@@ -40,22 -50,27 +52,30 @@@ def filter_implantation(context, prefix
  
  @register.inclusion_tag('admin/filter.html', takes_context=True)
  def filter_region_contrat(context):
 -    return {
 -        'title': u"région",
 -        'choices': prepare_choices(
 -            Region.objects.values_list('id', 'nom'),
 -            'dossier__poste__implantation__region', context,
 -            remove=['pays', 'nord_sud']
 -        )
 -    }
 +    request = context['request']
 +    user_groups = request.user.groups.all()
 +    if groups.grp_correspondants_rh in user_groups or\
 +         groups.grp_administrateurs in user_groups or\
 +         groups.grp_directeurs_bureau in user_groups:
 +        employe = get_employe_from_user(request.user)
 +        regions = Region.objects.filter(id=employe.implantation.region.id)
 +    else:
 +       regions = Region.objects.all()
 +    return {'title': u"région",
 +            'choices': prepare_choices(regions.values_list('id', 'nom'), 'dossier__poste__implantation__region', context, remove=['pays', 'nord_sud'])}
  
  @register.inclusion_tag('admin/filter.html', takes_context=True)
  def filter_region_dossier(context):
-     return {'title': u"région",
-             'choices': prepare_choices(Region.objects.values_list('id', 'nom'), 'poste__implantation__region', context, remove=['pays', 'nord_sud'])}
+     return {
+         'title': u"région",
+         'choices': prepare_choices(
+             Region.objects.values_list('id', 'nom'),
+             'poste__implantation__region', context,
+             remove=['pays', 'nord_sud']
+         )
+     }
  
  @register.inclusion_tag('admin/filter.html', takes_context=True)
  def filter_implantation_dossier(context):
@@@ -6,45 -6,41 +6,42 @@@ from itertools import izi
  import StringIO
  
  import pygraphviz as pgv
- from datamaster_modeles import models as ref
- from django.core.urlresolvers import reverse
- from django.db.models import Q
- from django.utils.encoding import smart_str
- from django.shortcuts import render_to_response, get_object_or_404
- from django.template import RequestContext
- from django.http import HttpResponse
  from django import forms
+ from django.conf import settings
  from django.contrib.auth.decorators import login_required
  from django.core.servers.basehttp import FileWrapper
+ from django.core.urlresolvers import reverse
+ from django.db.models import Q
+ from django.http import HttpResponse
+ from django.shortcuts import render, get_object_or_404
  
- from rh import models as rh
- from rh.lib import calc_remun
- from project.rh.decorators import drh_or_admin_required, in_one_of_group
- from rh.templatetags.rapports import SortHeaders
- from rh.change_list import RechercheTemporelle
- from rh import graph as rh_graph
- from rh.masse_salariale import MasseSalariale
- # pas de reference a DAE devrait etre refactorisé
- from dae.utils import get_employe_from_user
- from dae.decorators import redirect_interdiction
- from django.conf import settings
- from project.rh.decorators import in_drh_or_admin
- from project.rh import groups
+ from auf.django.references import models as ref
++from project import groups
++from project.decorators import drh_or_admin_required, in_one_of_group
+ from project.decorators import redirect_interdiction
 -from project.decorators import drh_or_admin_required
+ from project.decorators import region_protected
+ from project.groups import get_employe_from_user
 -from project.groups import grp_drh, grp_correspondants_rh
+ from project.rh import models as rh
+ from project.rh import graph as rh_graph
+ from project.rh.change_list import RechercheTemporelle
+ from project.rh.lib import calc_remun, get_lookup_params
+ from project.rh.masse_salariale import MasseSalariale
+ from project.rh.templatetags.rapports import SortHeaders
  
  
  @login_required
 +@drh_or_admin_required
  def profil(request):
      """Profil personnel de l'employé - éditable"""
-     rc = RequestContext(request)
-     c = {}
-     employe = rc['this_employe']
-     c['user'] = request.user
-     c['employe'] = employe
-     return render_to_response('rh/profil.html', c, rc)
+     employe = get_employe_from_user(user)
+     c = {
+       'user': request.user,
+       'employe': employe,
+     }
+     return render(request, 'rh/profil.html', c)
  
  
  @login_required
@@@ -478,62 -239,40 +278,53 @@@ def rapports_masse_salariale(request)
  
  
  @login_required
 -@drh_or_admin_required
 +@in_one_of_group((groups.grp_correspondants_rh,
 +    groups.grp_administrateurs,
 +    groups.grp_directeurs_bureau,
 +    groups.grp_drh,
 +    groups.grp_drh2))
- def rapports_employe_sans_contrat(request):
-     lookup_params = dict(request.GET.items())
-     if 'ot' in lookup_params:
-         del lookup_params['ot']
-     if 'o' in lookup_params:
-         del lookup_params['o']
-     for key, value in lookup_params.items():
-         if not isinstance(key, str):
-             # 'key' will be used as a keyword argument later, so Python
-             # requires it to be a string.
-             del lookup_params[key]
-             lookup_params[smart_str(key)] = value
-     employes_query = rh.Employe.objects
-     if 'o' in request.GET:
-         employes_query = employes_query.order_by(
-             ('-' if request.GET.get('ot') == "desc" else '') + request.GET['o']
-         )
-     employes = {}
+ def rapports_employes_sans_contrat(request):
+     lookup_params = get_lookup_params(request)
  
++    # régionalisation
 +    user_groups = request.user.groups.all()
 +    q_region = Q()
 +    if groups.grp_correspondants_rh in user_groups or\
 +       groups.grp_administrateurs in user_groups or\
 +       groups.grp_directeurs_bureau in user_groups:
 +        employe = get_employe_from_user(request.user)
 +        q_region = Q(poste__implantation__region=employe.implantation.region)
 +
-     dossiers_en_cours = rh.Dossier.objects.filter(q_region & (
-         Q(date_fin=None) | Q(date_fin__gt=date.today()))
-     )
-     tous_contrats_echus = rh.Contrat.objects.filter(
-         date_fin__lt=date.today(), dossier__in=dossiers_en_cours
-     )
-     contrats = tous_contrats_echus.filter(**lookup_params).all()
-     for c in contrats:
-         if c.dossier.employe.id not in employes.keys():
-             employes[c.dossier.employe.id] = {
-                 'employe': c.dossier.employe,
-                 'dossiers': []
-             }
-         employes[c.dossier.employe.id]['dossiers'] += [c.dossier]
+     # 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()),
++    dossiers_sans_contrat = rh.Dossier.objects.filter(q_region & (
++            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"# de l'employé"),
-         ("nom", u"Nom"),
-         ("prenom", u"Prénom"),
-         ("dossier", u"Dossiers"),
+         ("nom", u"Employé"),
+         ("dossier", u"Dossier : Poste"),
+         ("dossier_date_debut", u"Début occupation poste"),
+         ("dossier_date_fin", u"Fin occupation poste"),
      ]
      h = SortHeaders(
          request, headers, order_field_type="ot", order_field="o",
@@@ -686,11 -391,9 +443,9 @@@ def poste_apercu(request, poste_id)
          ),
          'media_url': settings.PRIVE_MEDIA_URL,
      }
-     return render_to_response(
-         'admin/rh/poste/apercu.html', c, RequestContext(request)
-     )
+     return render(request, 'admin/rh/poste/apercu.html', c)
  
 -
 +@region_protected(rh.Employe)
  def employe_apercu(request, employe_id):
      employe = get_object_or_404(rh.Employe, pk=employe_id)
      user_groups = request.user.groups.all()
@@@ -130,17 -127,18 +127,17 @@@ ADMIN_TOOLS_APP_INDEX_DASHBOARD = 'proj
  ADMIN_TOOLS_MENU = 'project.menu.CustomMenu'
  
  AJAX_LOOKUP_CHANNELS = {
-     'responsables' : ('dae.catalogues', 'Responsable'),
-     'dossiers' : ('dae.catalogues', 'Dossier'),
-     'dae_postes' : ('dae.catalogues', 'Poste'),
-     'pays' : ('rh.catalogues', 'Pays'),
-     'implantations' : ('rh.catalogues', 'Implantation'),
-     'typepostes' : ('rh.catalogues', 'TypePoste'),
-     'postes' : ('rh.catalogues', 'Poste'),
-     'valeurpoints' : ('rh.catalogues', 'ValeurPoint'),
-     'employes' : ('rh.catalogues', 'Employe'),
-     'dossiers' : ('rh.catalogues', 'Dossier'),
+     'responsables': ('project.dae.catalogues', 'Responsable'),
+     'dossiers': ('project.dae.catalogues', 'Dossier'),
+     'dae_postes': ('project.dae.catalogues', 'Poste'),
+     'pays': ('project.rh.catalogues', 'Pays'),
+     'implantations': ('project.rh.catalogues', 'Implantation'),
+     'typepostes': ('project.rh.catalogues', 'TypePoste'),
+     'postes': ('project.rh.catalogues', 'Poste'),
+     'valeurpoints': ('project.rh.catalogues', 'ValeurPoint'),
+     'employes': ('project.rh.catalogues', 'Employe'),
+     'dossiers': ('project.rh.catalogues', 'Dossier'),
  }
 -AJAX_SELECT_BOOTSTRAP = True
  AJAX_SELECT_INLINES = 'inline'
  
  
@@@ -171,8 -172,27 +171,29 @@@ TINYMCE_DEFAULT_CONFIG = 
  # django-sendfile
  SENDFILE_BACKEND = 'sendfile.backends.simple'
  
+ QBE_DISPLAY_DATABASES = False
+ # Il est *très* important de respecter la case.
+ QBE_CUSTOM_MODELS = {'Rh': {
+     'Employe': {},
+     'Poste': {},
+     'Dossier': {},
+     'Remuneration': {},
+     'Contrat': {},
+ }}
+ QBE_ALLOWED_FIELDS = {'Rh': {
+     'Employe': [
+         'nom', 'prenom', 'genre', 'date_naissance', 'situation_familiale',
+         'date_entree'
+     ],
+     'Poste': ['nom', 'date_debut', 'date_fin'],
+     'Dossier': [
+         'statut_residence', 'regime_travail',
+         'regime_travail_nb_heure_semaine', 'date_debut', 'date_fin'
+     ],
+     'Remuneration': ['montant', 'date_debut', 'date_fin'],
+     'Contrat': ['date_debut', 'date_fin'],
+ }}
++
 +SOUTH_TESTS_MIGRATE = False
diff --cc versions.cfg
@@@ -11,9 -12,9 +12,9 @@@ auf.django.auth = 0.5.5de
  auf.django.emploi = 1.0dev
  auf.django.metadata = 0.6dev
  auf.django.permissions = 0.1
 -auf.django.references = 0.11
++auf.django.references = 0.17
  auf.django.skin = 1.5
  auf.django.workflow = 0.15dev
- auf.django.references = 0.17
  odfpy = 0.9.4
  pygraphviz = 0.36