from auf.django.workflow.models import WorkflowCommentaire
from django import forms
-from django.core.urlresolvers import reverse
-from django.core.mail import mail_admins
from django.contrib import admin
-from django.contrib import messages
-from django.shortcuts import redirect
from reversion.admin import VersionAdmin
-from project.dae.models import Poste, Dossier, DossierFinalise, PosteFinalise
-from project.rh.decorators import in_drh_or_admin
+from project.dae.models import Poste, Dossier
class PosteAdmin(VersionAdmin):
form = StatutPosteForm
-class ImportAdmin(admin.ModelAdmin,):
-
- def _etat(self, obj):
- return obj.get_etat_display()
- _etat.short_description = u"État"
- _etat.admin_order_field = "etat"
-
- def has_delete_permission(self, request, obj=None):
- return False
-
- def has_add_permission(self, request):
- return False
-
- def has_change_permission(self, request, obj=None):
- return in_drh_or_admin(request.user)
-
- def get_actions(self, request):
- actions = super(ImportAdmin, self).get_actions(request)
- del actions['delete_selected']
- return actions
-
-
-class ImportDossierAdmin(ImportAdmin):
- search_fields = ('employe__nom', 'employe__prenom', 'poste__nom', )
- list_display = ('_poste', '_implantation', '_employe', '_dae', '_etat')
- list_filter = ('poste__implantation', 'etat', )
- actions = ['importer_dans_RH', ]
-
- def _employe(self, obj):
- return obj.employe
-
- def _poste(self, obj):
- rh = obj.poste.rh_importation()
- if rh is not None:
- extra = u"<a href='%s' style='color: red;'> (déjà importé)</a>" % \
- reverse('admin:rh_poste_change', args=(rh.id,))
- else:
- extra = u""
-
- return u"%s%s" % (obj.poste.nom, extra)
- _poste.allow_tags = True
-
- def _implantation(self, obj):
- return obj.poste.implantation
- _implantation.short_description = u"Implantation"
- _implantation.admin_order_field = "poste__implantation"
-
- def _dae(self, obj):
- url = reverse('embauche_consulter', args=(obj.id, ))
- return "<a href='%s'>voir la DAE</a>" % url
- _dae.allow_tags = True
-
- def importer_dans_RH(self, request, data):
- selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
- if len(selected) > 1:
- messages.add_message(request, messages.ERROR,
- u"Un seul dossier ne peut être importé à la fois")
- url = reverse('admin:dae_dossierfinalise_changelist')
- return redirect(url)
-
- dae = [d for d in Dossier.objects.filter(id__in=selected)]
- for d in dae:
- try:
- d.importer(dry_run=True)
- copie = d.importer()
- messages.add_message(request, messages.SUCCESS,
- u"%s importé dans RH" % d)
- url = reverse('admin:rh_dossier_change', args=(copie.id, ))
- except Exception, e:
- mail_admins('DAE import', unicode(e))
- messages.add_message(request, messages.ERROR, u"%s ne peut pas\
- être importé" % d)
- url = reverse('admin:dae_dossierfinalise_changelist')
- return redirect(url)
-
-
-class ImportPosteAdmin(ImportAdmin):
- search_fields = ('poste__nom', )
- list_display = ('nom', '_implantation', '_dae', '_etat',)
- list_filter = ('implantation',)
- actions = ['importer_dans_RH', ]
-
- def _implantation(self, obj):
- return obj.implantation
- _implantation.short_description = u"Implantation"
- _implantation.admin_order_field = "implantation"
-
- def _dae(self, obj):
- url = reverse('poste_consulter', args=("dae-%s" % obj.id, ))
- return "<a href='%s'>voir le poste dans DAE</a>" % url
- _dae.allow_tags = True
-
- def importer_dans_RH(self, request, data):
- selected = request.POST.getlist(admin.ACTION_CHECKBOX_NAME)
- if len(selected) > 1:
- messages.add_message(request, messages.ERROR,
- u"Un seul poste ne peut être importé à la fois")
- url = reverse('admin:dae_postefinalise_changelist')
- return redirect(url)
- dae = [d for d in Poste.objects.filter(id__in=selected)]
- for p in dae:
- try:
- p.importer(dry_run=True)
- copie = p.importer()
- messages.add_message(request, messages.SUCCESS,
- u"%s importé dans RH" % d)
- url = reverse('admin:rh_poste_change', args=(copie.id, ))
- except Exception, e:
- mail_admins('DAE import', unicode(e))
- messages.add_message(request, messages.ERROR, u"%s ne peut pas\
- être importé" % p)
- url = reverse('admin:dae_postefinalise_changelist')
- return redirect(url)
-
-
admin.site.register(Poste, PosteAdmin)
admin.site.register(Dossier, DossierAdmin)
admin.site.register(ProxyDossierStatut, DossierStatutAdmin)
admin.site.register(ProxyPosteStatut, PosteStatutAdmin)
-admin.site.register(DossierFinalise, ImportDossierAdmin)
-admin.site.register(PosteFinalise, ImportPosteAdmin)
+++ /dev/null
-# -*- coding: utf-8 -*-
-
-import sys
-import codecs
-import os
-import shutil
-
-from django.conf import settings
-from project.rh import models as rh
-import models as dae
-
-SKIP = "** SKIP **"
-
-class SuperCopier(object):
- """
- Classe abstraite pour faire de la copie profonde sur des objets en BD.
- Elle prévoit des hooks pour traiter des propriétés en particulier.
- """
- dry_run = True
- verbosity = 0
- stdout = codecs.getwriter('utf8')(sys.stdout)
-
- def __init__(self, dry_run=True, verbosity=0):
- self.verbosity = verbosity
- self.dry_run = dry_run
-
- def out(self, txt, level=0):
- if self.verbosity >= level:
- self.stdout.write(txt)
-
- def clean_id(self, source, copy, parent, field, value):
- self.out(SKIP, 2)
- return []
-
- def parent(self, parent, child):
- if not self.dry_run:
- parent.save()
- klass = parent.__class__.__name__.lower()
- k = "%s_id" % klass
- setattr(child, k, parent.id)
-
- def duplicate(self, obj, parent=None, level=0):
- klass = getattr(rh, obj.__class__.__name__)
- copy = klass()
-
- indent = " "*level*4
- self.out(u"\n%s [%s] %s" % (indent, str(obj.__class__),
- obj), 1)
-
- for f in obj._meta.fields:
- value = getattr(obj, f.name)
-
- self.out(u"\n%s * %s: %s " % (indent, f.name, value), 2)
-
- cleanup_fct = "clean_%s" % f.name
- if hasattr(self, cleanup_fct):
- cleaner = getattr(self, cleanup_fct)
- cleaner(obj, copy, parent, f, value)
- else:
- setattr(copy, f.name, value)
-
- for obj_composition in obj._meta._related_objects_cache:
- app_label, dummy = obj_composition.name.split(':')
- field_name = obj_composition.field.rel.related_name
- if field_name == '+':
- continue
- self.out(u"\n%s + [%s] %s " % (indent, app_label, field_name), 1)
- try:
- cleanup_fct = "clean_%s" % field_name
- if hasattr(self, cleanup_fct):
- cleaner = getattr(self, cleanup_fct)
- children = cleaner(obj, copy, parent, f, value)
- else:
- children = getattr(obj, field_name).all()
- except Exception, e:
- # no reverse relation
- self.out(" %s %s" % (field_name, str(e)), 1)
- continue
-
- for child in children:
- child_copy = self.duplicate(child, parent=copy, level=level+1,)
- parentship_fct = "parent_%s" % (field_name)
- if hasattr(self,parentship_fct):
- parentship = getattr(self, parentship_fct)
- else:
- parentship = getattr(self, "parent")
- parentship(copy, child_copy)
- if not self.dry_run:
- child_copy.save()
-
- return copy
-
- def copy(self, obj):
- return self.duplicate(obj)
-
-
-class PosteCopier(SuperCopier):
-
- def copy(self, obj):
- copy = super(PosteCopier, self).copy(obj)
- if not self.dry_run:
- dae.ImportPoste(dae=obj, rh=copy).save()
- return copy
-
- def clean_rh_dossiers(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_comparaisons_internes(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_financements(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_pieces(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_dae_dossiers(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_poste(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_fichier(self, source, copy, parent, field, value):
- if not self.dry_run and parent.id is None:
- parent.save()
- filename = value.path.split('/')[-1]
- copy.poste_id = parent.id
- new_value = rh.poste_piece_dispatch(copy, filename)
-
- app, model, id, f = new_value.split('/')
- app_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app)
- model_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app, model)
- id_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app, model, id)
- if not os.path.exists(app_path):
- os.mkdir(app_path)
- if not os.path.exists(model_path):
- os.mkdir(model_path)
- if not os.path.exists(id_path):
- os.mkdir(id_path)
- src = value.path
- dst = os.path.join(settings.PRIVE_MEDIA_ROOT, new_value)
- shutil.copy(src, dst)
- setattr(copy, field.name, new_value)
-
-
-class DossierCopier(SuperCopier):
-
- def copy(self, obj):
- copy = super(DossierCopier, self).copy(obj)
- if not self.dry_run:
- # update des dates partout
- date_debut = obj.contrat_date_debut
- date_fin = obj.contrat_date_fin
- copy.date_debut = date_debut
- copy.date_fin = date_fin
- copy.save()
- for r in copy.rh_remunerations.all():
- r.date_debut = date_debut
- r.date_fin = date_fin
- r.save()
- # log d'import
- dae.ImportDossier(dae=obj, rh=copy).save()
- return copy
-
- def clean_rh_contrats(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_dossierpieces(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_comparaisons(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_rh_remunerations(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
- def clean_dossier(self, source, copy, parent, field, value):
- self.out(SKIP, 1)
- return []
-
-
- def clean_employe(self, source, copy, parent, field, value):
- if source.employe.id_rh is not None:
- copy.employe = source.employe.id_rh
- else:
- nouvel_employe = rh.Employe()
- nouvel_employe.nom = source.employe.nom
- nouvel_employe.prenom = source.employe.prenom
- nouvel_employe.genre = source.employe.genre
- nouvel_employe.save()
- copy.employe = nouvel_employe
-
- def clean_poste(self, source, copy, parent, field, value):
- # poste comparaison a un champs nommé poste
- if isinstance(value, unicode):
- setattr(copy, field.name, value)
- return
-
- if dae.ImportPoste.objects.filter(dae=value).exists():
- poste = dae.ImportPoste.objects.get(dae=value).rh
- else:
- copier = PosteCopier(verbosity=self.verbosity,
- dry_run=self.dry_run)
- poste = copier.copy(value)
- copy.poste_id = poste.id
-
- def clean_fichier(self, source, copy, parent, field, value):
- if not self.dry_run and parent.id is None:
- parent.save()
- filename = value.path.split('/')[-1]
- copy.dossier_id = parent.id
-
- ct = copy.__class__.__name__.lower()
- if ct == 'contrat':
- new_value = rh.contrat_dispatch(copy, filename)
- elif ct == 'dossierpiece':
- new_value = rh.dossier_piece_dispatch(copy, filename)
- else:
- raise Exception('fichier %s à mapper!' % ct)
-
- app, model, id, f = new_value.split('/')
- app_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app)
- model_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app, model)
- id_path = os.path.join(settings.PRIVE_MEDIA_ROOT, app, model, id)
- if not os.path.exists(app_path):
- os.mkdir(app_path)
- if not os.path.exists(model_path):
- os.mkdir(model_path)
- if not os.path.exists(id_path):
- os.mkdir(id_path)
- src = value.path
- dst = os.path.join(settings.PRIVE_MEDIA_ROOT, new_value)
- shutil.copy(src, dst)
- setattr(copy, field.name, new_value)
class Meta:
model = dae.Dossier
fields = ('dae_numerisee',)
-
-
-class DAEImportableForm(forms.Form):
- qs_poste = dae.Poste.objects.filter(etat=POSTE_ETAT_FINALISE)
- qs_dossier = dae.Dossier.objects.filter(etat=DOSSIER_ETAT_FINALISE)
- poste = forms.ModelChoiceField(
- queryset=qs_poste, label="Poste finalisé", required=False
- )
- dossier = forms.ModelChoiceField(
- queryset=qs_dossier, label="DAE finalisée", required=False
- )
-
- def clean_poste(self):
- poste = self.cleaned_data['poste']
- if poste is not None and poste.est_importe():
- raise forms.ValidationError("Ce poste a déjà été importé")
- return poste
-
- def clean_dossier(self):
- dossier = self.cleaned_data['dossier']
- if dossier is not None and not dossier.poste.est_importe():
- raise forms.ValidationError(
- "Le poste de ce dossier doit être importé avant de pouvoir "
- "importer le dossier."
- )
- return dossier
-
- def importer_poste(self):
- poste = self.cleaned_data['poste']
- if poste is not None and not poste.est_importe():
- poste.importer()
+++ /dev/null
-# -*- encoding: utf-8 -*-
-
-from django.core.management.base import BaseCommand
-
-from project.dae import models as dae
-
-class Command(BaseCommand):
-
-
- def handle(self, *args, **options):
-
- if len(args) < 2:
- print len(args)
- self.stdout.write("dae <modele> <id> <run>\n")
- return
-
- classname = args[0]
- klass = getattr(dae, classname, None)
- if klass is None:
- self.stdout.write("Le modèle %s n'existe pas dans DAE.\n" % classname)
-
- id = int(args[1])
- try:
- obj = klass.objects.get(id=id)
- except:
- self.stdout.write("L'id %s n'existe pas pour le modèle %s dans DAE.\n" % \
- (id, classname))
- return
-
-
- copy = obj.importer()
- self.stdout.write(u"\n[%s] DAE:%s => RH:%s\n" %
- (obj.__class__.__name__, obj.id, copy.id))
-
class DossierComparaisonManager(RHDossierComparaisonManager, TodoManagerMixin):
pass
-
-class DossierFinaliseManager(models.Manager):
- """
- Dossiers finalisés, qui ne sont pas encore importés
- """
- def get_query_set(self):
- from dae.models import ImportDossier
- dae_importees = [str(i.dae_id) for i in ImportDossier.objects.all()]
- qs = super(DossierFinaliseManager, self).get_query_set().all()
- if len(dae_importees) > 0:
- qs = qs.extra(where=['dae_dossier.id NOT IN (%s)' % ", ".join(dae_importees)])
- return qs
-
-
-class PosteFinaliseManager(models.Manager):
- """
- Dossiers finalisés, qui ne sont pas encore importés
- """
- def get_query_set(self):
- from dae.models import ImportPoste
- dae_importees = [str(i.dae_id) for i in ImportPoste.objects.all()]
-
- qs = super(PosteFinaliseManager, self).get_query_set().all()
- if len(dae_importees) > 0:
- qs = qs.extra(where=['dae_poste.id NOT IN (%s)' % ", ".join(dae_importees)])
- return qs
-
-
from django.db import models
from django.db.models import Q
-from project.dae.exporter import DossierCopier, PosteCopier
-from project.dae.managers import \
- PosteManager, DossierManager, DossierFinaliseManager, \
- PosteFinaliseManager
+from project.dae.managers import PosteManager, DossierManager
from project.dae.workflow import PosteWorkflow, DossierWorkflow
from project.dae.workflow import \
DOSSIER_ETAT_DRH_FINALISATION, DOSSIER_ETAT_REGION_FINALISATION, \
# Modèle existant
id_rh = models.ForeignKey(
- rh.Poste, null=True, related_name='+', editable=False,
+ rh.Poste, null=True, related_name='postes_dae', editable=False,
verbose_name=u"Mise à jour du poste"
)
return []
return self.id_rh.rh_dossiers.all()
- def rh_importation(self):
- if ImportPoste.objects.filter(dae=self).exists():
- return ImportPoste.objects.get(dae=self).rh
- else:
- return None
-
- def importer(self, verbosity=0, dry_run=False):
- copieur = PosteCopier(verbosity=verbosity, dry_run=dry_run)
- return copieur.copy(self)
-
def dans_rh(self):
"""
Retourne le poste RH s'il existe.
self.poste.implantation, self.poste.nom, self.employe
)
- def importer(self, verbosity=0, dry_run=False):
- copieur = DossierCopier(verbosity=verbosity, dry_run=dry_run)
- return copieur.copy(self)
-
def dans_rh(self):
"""
Retourne le dossier associé dans le système RH ou ``None`` s'il n'y
class Contrat(rh.Contrat_):
pass
-
-
-class DossierFinalise(Dossier):
-
- objects = DossierFinaliseManager()
-
- class Meta:
- proxy = True
- verbose_name = "Import d'un dossier dans RH"
- verbose_name_plural = "Import des dossiers dans RH"
-
-
-class PosteFinalise(Poste):
-
- objects = PosteFinaliseManager()
-
- class Meta:
- proxy = True
- verbose_name = "Import d'un poste dans RH"
- verbose_name_plural = "Import des postes dans RH"
-
-
-# modèle de liaison entre les systèmes
-
-class ImportDossier(models.Model):
- dae = models.ForeignKey('dae.Dossier', related_name='+')
- rh = models.ForeignKey('rh.Dossier', related_name='+')
-
-
-class ImportPoste(models.Model):
- dae = models.ForeignKey('dae.Poste', related_name='+')
- rh = models.ForeignKey('rh.Poste', related_name='+')
url(r'^embauches/(\d+)/dae_numerisee/supprimer$',
'dae_numerisee_supprimer', name='dae_numerisee_supprimer'),
- url(r'^importer$', 'importer_choix_dossier', name='importer_dae'),
-
# ajax
url(r'^employe$', 'employe', name='employe'),
url(r'^employe/(?P<key>.*)$', 'employe', name='employe'),
PosteComparaisonFormSet, DossierWorkflowForm, ChoosePosteForm, \
EmployeForm, DossierForm, DossierPieceForm, \
DossierComparaisonFormSet, RemunForm, ContratForm, DAENumeriseeForm, \
- label_poste_display, DAEImportableForm
+ label_poste_display
from project.dae.mail import send_drh_finalisation_mail
from project.dae.workflow import \
DOSSIER_ETAT_FINALISE, DOSSIER_ETAT_REGION_FINALISATION, \
return redirect_interdiction(request)
-@login_required
-def importer_choix_dossier(request):
- method = request.method
- params = getattr(request, method, None)
- if params:
- form = DAEImportableForm(params)
- if form.is_valid():
- form.importer_poste()
- messages.add_message(
- request, messages.SUCCESS, "L'importation a réussie."
- )
- else:
- form = DAEImportableForm()
-
- vars = dict(form=form, )
- return render_to_response('admin/dae/importer_choix_dossier.html', vars,
- RequestContext(request))
-
-
# AJAX SECURITE non nécessaire
def coefficient(request):
"""
from django.utils.translation import ugettext_lazy as _
-from django.core.urlresolvers import reverse
from admin_tools.dashboard import modules, Dashboard, AppIndexDashboard
from admin_tools.utils import get_admin_site_name
Custom index dashboard for SIGMA.
"""
def init_with_context(self, context):
- site_name = get_admin_site_name(context)
# append an app list module for "Applications"
self.children.append(modules.AppList(
def _dae(self, d):
apercu_link = ""
- if dae.ImportDossier.objects.filter(rh=d).exists():
- dae_id = dae.ImportDossier.objects.get(rh=d).dae_id
+ dossiers_dae = d.dossiers_dae.all()
+ if len(dossiers_dae) > 0:
+ dossier_dae = dossiers_dae[0]
apercu_link = u"""<a title="Aperçu du dossier"
onclick="return showAddAnotherPopup(this);"
href='%s'>
<img src="%simg/loupe.png" />
</a>""" % \
- (reverse('embauche_consulter', args=(dae_id,)),
+ (reverse('embauche_consulter', args=(dossier_dae.id,)),
settings.STATIC_URL,
)
return apercu_link
def _dae(self, poste):
apercu_link = ""
- if dae.ImportPoste.objects.filter(rh=poste).exists():
- dae_id = dae.ImportPoste.objects.get(rh=poste).dae_id
- apercu_link = u"""<a title="Aperçu du dossier"
- onclick="return showAddAnotherPopup(this);"
- href='%s'>
- <img src="%simg/loupe.png" />
- </a>""" % \
- (reverse('poste_consulter', args=("dae-%s" % dae_id,)),
- settings.STATIC_URL,
- )
+ postes_dae = poste.postes_dae.all()
+ if len(postes_dae) > 0:
+ poste_dae = postes_dae[0]
+ apercu_link = \
+ u'<a title="Aperçu du dossier" href="%s" ' \
+ u'onclick="return showAddAnotherPopup(this);">' \
+ u'<img src="%simg/loupe.png" /></a>' % (reverse(
+ 'poste_consulter', args=("dae-%s" % poste_dae.id,)
+ ), settings.STATIC_URL)
return apercu_link
_dae.allow_tags = True
_dae.short_description = u"DAE"
Ajouter Dossier
</a>
</li>
- {% comment %}
- <li>
- <a href="{% url importer_dae %}" class="addlink">
- Importer une DAE
- </a>
- </li>
- {% endcomment %}
{% endblock %}
{% block search %}
<li class="{% menu_actif request '^embauches_finalisees$' %}">
<a href="{% url embauches_finalisees %}">Embauches finalisées</a>
</li>
- {% if request.user|peut_importer %}
- <li>
- <a href="{% url admin:dae_dossierfinalise_changelist %}">Importation des embauches</a>
- </li>
- {% endif %}
- {% if request.user|peut_importer %}
- <li>
- <a href="{% url admin:dae_postefinalise_changelist %}">Importation des postes</a>
- </li>
- {% endif %}
</ul>
- </li>
- {% endif %}
+ </li>
+ {% endif %}
{% if perms.rh %}
<li>