--- /dev/null
+*.pyc
+*egg-info
+build
+dist
--- /dev/null
+auf.django.emploi
+===================
+
+0.1
+---
+
+* Création du module :
--- /dev/null
+auf.django.emploi
+===================
+
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except:
+ # bootstrapping
+ pass
--- /dev/null
+try:
+ __import__('pkg_resources').declare_namespace(__name__)
+except:
+ # bootstrapping
+ pass
--- /dev/null
+# -*- encoding: utf-8 -*-
+
+import os
+from django import forms
+from django.contrib import admin
+from django.forms.models import inlineformset_factory
+from django.forms.widgets import CheckboxSelectMultiple
+from django.forms import ModelForm
+
+from captcha.fields import CaptchaField
+
+from recrutement import models as recr
+
+################################################################################
+# OFFRE EMPLOI
+################################################################################
+class CandidatPieceForm(inlineformset_factory(recr.Candidat,
+ recr.CandidatPiece)):
+ nom = forms.MultipleChoiceField(choices=recr.TYPE_PIECE_CHOICES,
+ widget=CheckboxSelectMultiple)
+
+class PostulerOffreEmploiForm(ModelForm):
+ captcha = CaptchaField()
+
+ def __init__(self, *args, **kwargs):
+ self.offre_emploi = kwargs.pop('offre_emploi')
+ super(PostulerOffreEmploiForm, self).__init__(*args, **kwargs)
+
+ def save(self, *args, **kwargs):
+ kwargs2 = kwargs.copy()
+ kwargs2['commit'] = False
+ postulation = super(PostulerOffreEmploiForm, self).save(*args, **kwargs2)
+ if 'commit' not in kwargs or kwargs['commit']:
+ postulation.save()
+ return postulation
+
+ class Meta:
+ model = recr.Candidat
+ exclude = ('actif', 'offre_emploi',)
+ fields = ('nom', 'prenom', 'genre', 'nationalite', 'situation_famille',
+ 'nombre_dependant', 'niveau_diplome', 'employeur_actuel',
+ 'poste_actuel', 'domaine_professionnel', 'telephone',
+ 'email', 'adresse', 'ville', 'code_postal', 'etat_province',
+ 'pays', 'captcha', )
+
+# TODO: Vérifier si on garde, pour l'envoi automatique d'un email lors de la
+# postulation de l'offre d'emploi
+################################################################################
+# TEMPLATE COURRIEL
+################################################################################
+class CandidatCourrielTemplateForm(ModelForm):
+ def get_template(self):
+ return self.data['template']
+
+ class Meta:
+ model = recr.CandidatCourriel
+ fields = ('template', )
+
+class CandidatCourrielForm(ModelForm):
+ def __init__(self, *args, **kwargs):
+ self.candidats = kwargs.pop('candidats')
+ self.template = kwargs.pop('template')
+ super(CandidatCourrielForm, self).__init__(*args, **kwargs)
+
+ def save(self):
+ super(CandidatCourrielForm, self).save()
+
+ class Meta:
+ model = recr.CandidatCourriel
+ fields = ('sujet', 'plain_text', 'html')
+
--- /dev/null
+# -=- encoding: utf-8 -=-
+
+import datetime
+from django.core.files.storage import FileSystemStorage
+from tinymce import models as tinymce_models
+from django.db import models
+import settings
+#from private_files import PrivateFileField
+
+import datamaster_modeles.models as ref
+from project.rh.models import Poste
+
+### CONSTANTES ###
+# HELP_TEXT
+HELP_TEXT_NB_DEPENDANT = "Le nombre de personnes à charge"
+HELP_TEXT_FORMAT_DATE = "Le format de la date est AAAA-MM-JJ"
+HELP_TEXT_TAGS_ACCEPTES = "Pour le texte, les variables disponibles sont : \
+ {{ nom_candidat }} {{ prenom_candidat }} \
+ {{ offre_emploi }}. Ces champs seront \
+ automatiquement remplacés par les informations de \
+ chaque candidat."
+
+
+STATUT_OFFRE_EMPLOI_CHOICES = (
+ ('NOUV', 'Nouveau'),
+ ('AFFI', 'Offre d\'emploi en affichage'),
+ ('EVAL', 'En évaluation des candidatures'),
+ ('ENTR', 'En entrevue'),
+ ('TERM', 'Terminé'),
+)
+
+# CANDIDAT
+GENRE_CHOICES = (
+ ('M', 'Homme'),
+ ('F', 'Femme'),
+)
+SITUATION_CHOICES = (
+ ('C', 'Célibataire'),
+ ('F', 'Conjoint de fait'),
+ ('M', 'Marié'),
+ ('D', 'Divorcé'),
+)
+STATUT_CHOICES = (
+ ('NOUV', 'Nouveau'),
+ ('REC', 'Recevable'),
+ ('SEL', 'Sélectionné'),
+ ('REF', 'Refusé'),
+ ('ACC', 'Accepté'),
+)
+
+# PIECE CANDIDAT
+TYPE_PIECE_CHOICES = (
+ ('CV','CV'),
+ ('LET','Lettre'),
+ ('AUT','Autre'),
+)
+
+# Abstracts
+class Metadata(models.Model):
+ """
+ Méta-données AUF.
+ Metadata.actif = flag remplaçant la suppression.
+ actif == False : objet réputé supprimé.
+ """
+ actif = models.BooleanField(default=True)
+ date_creation = models.DateField(auto_now_add=True,
+ help_text=HELP_TEXT_FORMAT_DATE, )
+
+ class Meta:
+ abstract = True
+
+class ProxyPoste(Poste):
+ class Meta:
+ proxy = True
+
+ def __unicode__(self):
+ return '%s [%s]' % (self.nom, self.id)
+
+class OffreEmploi(Metadata):
+ est_affiche = models.BooleanField(default=False,
+ verbose_name="En affichage sur le site")
+ statut = models.CharField(max_length=4, choices=STATUT_OFFRE_EMPLOI_CHOICES,
+ default='NOUV')
+ nom = models.CharField(max_length=255)
+ resume = models.TextField(verbose_name="Résumé")
+ description = tinymce_models.HTMLField()
+ poste = models.ForeignKey(ProxyPoste, db_column='poste')
+ date_limite = models.DateField(verbose_name="Date limite",
+ help_text=HELP_TEXT_FORMAT_DATE,)
+ region = models.ForeignKey(ref.Region, db_column='region',
+ verbose_name="Région")
+ bureau = models.ForeignKey(ref.Bureau, db_column='bureau', )
+ duree_affectation = models.CharField(max_length=255,
+ verbose_name="Durée de l'affectation")
+ renumeration = models.CharField(max_length=255,
+ verbose_name='Rénumération')
+ debut_affectation = models.DateField(verbose_name="Début de l'affectation",
+ help_text=HELP_TEXT_FORMAT_DATE,)
+ lieu_affectation = models.ForeignKey(ref.Implantation,
+ db_column='implantation',
+ verbose_name="Lieu d'affectation")
+
+ class Meta:
+ db_table = 'emploi_offreemploi'
+ verbose_name_plural = "offres d'emploi"
+
+ def __unicode__(self):
+ return '%s [%s]' % (self.nom, self.id)
+
+class Candidat(Metadata):
+ statut = models.CharField(max_length=4, choices=STATUT_CHOICES,
+ default='NOUV')
+ offre_emploi = models.ForeignKey('OffreEmploi', db_column='offre_emploi',
+ related_name='+')
+ prenom = models.CharField(max_length=255, verbose_name='Prénom', )
+ nom = models.CharField(max_length=255)
+ genre = models.CharField(max_length=1, choices=GENRE_CHOICES)
+ nationalite = models.ForeignKey(ref.Pays,
+ db_column='nationalite', related_name='+',
+ verbose_name='Nationalité')
+ situation_famille = models.CharField(max_length=1,
+ choices=SITUATION_CHOICES,
+ verbose_name='Situation familiale', )
+ nombre_dependant = models.IntegerField(verbose_name='Nombre de dépendant',
+ help_text=HELP_TEXT_NB_DEPENDANT, )
+ niveau_diplome = models.CharField(max_length=255,
+ verbose_name='Niveau du diplôme')
+ employeur_actuel = models.CharField(max_length=255, )
+ poste_actuel = models.CharField(max_length=255, )
+ domaine_professionnel = models.CharField(max_length=255, )
+ telephone = models.CharField(max_length=255, verbose_name='Téléphone', )
+ email = models.EmailField(max_length=255, verbose_name = 'Courriel', )
+
+ # Adresse
+ adresse = models.CharField(max_length=255)
+ ville = models.CharField(max_length=255)
+ etat_province = models.CharField(max_length=255,
+ verbose_name="État/Province")
+ code_postal = models.CharField(max_length=255, blank=True)
+ pays = models.ForeignKey(ref.Pays, db_column='pays',
+ related_name='+')
+
+ def __unicode__(self):
+ return '%s %s [%s]' % (self.prenom, self.nom, self.id)
+
+ class Meta:
+ db_table = 'emploi_candidat'
+
+# Upload de fichiers
+storage_prive = FileSystemStorage(settings.PRIVE_MEDIA_ROOT,
+ base_url=settings.PRIVE_MEDIA_URL)
+
+def candidat_piece_dispatch(instance, filename):
+ path = "offre_emploi/%s_%s/%s/%s_%s" % (instance.candidat.nom,
+ instance.candidat.prenom, instance.nom, instance.candidat.id,
+ filename)
+ return path
+
+class CandidatPiece(models.Model):
+ candidat = models.ForeignKey(Candidat, db_column='candidat',
+ related_name='candidat_piece')
+ nom = models.CharField(max_length=3, choices=TYPE_PIECE_CHOICES)
+ #path = PrivateFileField("file", upload_to=candidat_piece_dispatch)
+ path = models.FileField(verbose_name="Fichier",
+ upload_to=candidat_piece_dispatch,
+ storage=storage_prive, )
+
+ class Meta:
+ db_table = 'emploi_evaluateur'
+ verbose_name = "pièce jointe"
+ verbose_name_plural = "pièces jointes"
+
+ def __unicode__(self):
+ return '%s' % (self.nom)
--- /dev/null
+<table>
+ {% for f in piecesForm.management_form %}
+ {{ f }}
+ {% endfor %}
+ <tr>
+ <th></th>
+ {% for field in piecesForm.forms.0 %}
+ {% if not field.is_hidden %}
+ <th>{{ field.label }}</th>
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% for f in piecesForm.forms %}
+ <tr>
+ <td>
+ {{ f.errors }}
+ {% if f.initial.fichier %}
+ <a href="{{ f.initial.fichier.url }}" target="_blank">Télécharger</a>
+ {% endif %}
+ </td>
+ {% for field in f %}
+ {% if not field.is_hidden %}
+ <td>{{ field }}</td>
+ {% else %}
+ {{ field }}
+ {% endif %}
+ {% endfor %}
+ </tr>
+ {% endfor %}
+</table>
--- /dev/null
+{% extends 'base.html' %}
+{% load adminmedia %}
+
+{% block title %}RH{% endblock %}
+{% block titre %}Ressources humaines{% endblock %}
+{% block sous_titre %}Accueil{% endblock %}
+
+{% block main %}
+<div id="content-main">
+ {% block object-tools %}{% endblock %}
+
+
+
+
+ <div class="module">
+ <h2>Poster pour un appel d'offre d'emploi</h2>
+ </div>
+
+ <form action="" method="post" enctype="multipart/form-data">
+ <fieldset>
+ <h2>Informations personnelles</h2>
+ <table id="informations_personnelles">
+ <tbody>
+ <tr>
+ <td>{{ form.prenom.label }}</td>
+ <td>{{ form.prenom }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nom.label }}</td>
+ <td>{{ form.nom }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.genre.label }}</td>
+ <td>{{ form.genre }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nationalite.label }}</td>
+ <td>{{ form.nationalite }}</td>
+ <tr>
+ <td>{{ form.situation_famille.label }}</td>
+ <td>{{ form.situation_famille }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.nombre_dependant.label }}</td>
+ <td>{{ form.nombre_dependant }}<br />
+ <span class="info">{{ form.nombre_dependant.help_text }}
+ </span>
+ </td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Coordonnées</h2>
+ <table id="coordonnees">
+ <tbody>
+ <tr>
+ <td>{{ form.telephone.label }}</td>
+ <td>{{ form.telephone }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.email.label }}</td>
+ <td>{{ form.email }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.adresse.label }}</td>
+ <td>{{ form.adresse }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.ville.label }}</td>
+ <td>{{ form.ville }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.etat_province.label }}</td>
+ <td>{{ form.etat_province }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.code_postal.label }}</td>
+ <td>{{ form.code_postal }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.pays.label }}</td>
+ <td>{{ form.pays }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Informations professionnelles</h2>
+ <table id="informations_professionnelles">
+ <tbody>
+ <tr>
+ <td>{{ form.niveau_diplome.label }}</td>
+ <td>{{ form.niveau_diplome }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.employeur_actuel.label }}</td>
+ <td>{{ form.employeur_actuel }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.poste_actuel.label }}</td>
+ <td>{{ form.poste_actuel }}</td>
+ </tr>
+ <tr>
+ <td>{{ form.domaine_professionnel.label }}</td>
+ <td>{{ form.domaine_professionnel }}</td>
+ </tr>
+ </tbody>
+ </table>
+ </fieldset>
+ <fieldset>
+ <h2>Pièces jointes</h2>
+ <p class="info">CV, lettre de motivation...</p>
+ {% include "recrutement/pieces.html" %}
+ </fieldset>
+ <fieldset>
+ <h2>Vérification CAPTCHA</h2>
+ <p class="info">Entrez les caractères figurant dans l'image ci-dessous.</p>
+ <tr>
+ <td>
+ {{ form.captcha }}
+ {{ form.captcha.errors }}
+ </td>
+ </tr>
+ </fieldset>
+ <div class="submit-row">
+ <input type="submit" name="save" value="Enregistrer" />
+ </div>
+ </form>
+
+
+
+</div>
+
+{% endblock %}
--- /dev/null
+# -*- encoding: utf-8 -*-
+
+from django.contrib import messages
+from django.shortcuts import render_to_response, redirect, get_object_or_404
+from django.template import Context, RequestContext, Template
+from django.core.mail import EmailMultiAlternatives
+
+from forms import *
+from models import *
+from project.recrutement import models as recr
+
+def postuler_appel_offre(request):
+ vars = dict()
+ offre_emploi = get_object_or_404(OffreEmploi, id=request.GET.get('id'))
+ candidat = Candidat()
+ candidat.offre_emploi = offre_emploi
+
+ if request.method == "POST":
+ form = PostulerOffreEmploiForm(request.POST,
+ instance=candidat, offre_emploi=offre_emploi)
+ piecesForm = CandidatPieceForm(request.POST, request.FILES,
+ instance=candidat)
+ if form.is_valid() and piecesForm.is_valid():
+ offre = form.save()
+ piecesForm.instance = offre
+ piecesForm.save()
+
+ courriel_template = CourrielTemplate.objects.\
+ get(nom_modele='Confirmation postulation (automatique)')
+ send_templated_email(candidat, courriel_template)
+
+ messages.add_message(request, messages.SUCCESS,
+ "Votre application à l'appel d'offre d'emploi a \
+ été effectuée.")
+ return redirect("admin:recrutement_offreemploi_changelist")
+ else:
+ messages.add_message(request, messages.ERROR,
+ 'Il y a des erreurs dans le formulaire.')
+ else:
+ form = PostulerOffreEmploiForm(instance=candidat,
+ offre_emploi=offre_emploi)
+ piecesForm = CandidatPieceForm(instance=candidat)
+
+ vars.update(dict(form=form, candidat=candidat, piecesForm=piecesForm, ))
+
+ return render_to_response('recrutement/postuler_appel_offre.html', vars,
+ RequestContext(request))
+
+def send_templated_email(candidat, template):
+ # Sujet
+ sujet_template = Template(template.sujet)
+ dict_sujet = {"offre_emploi": candidat.offre_emploi.nom,}
+ sujet = Context(dict_sujet)
+ # Plain text
+ texte_template = Template(template.plain_text)
+ dict_texte = {"nom_candidat": candidat.nom,
+ "prenom_candidat": candidat.prenom,
+ "offre_emploi": candidat.offre_emploi.nom,}
+ texte = Context(dict_texte)
+ # HTML text
+ html_template = Template(template.html)
+ texte_html = Context(dict_texte)
+ msg = EmailMultiAlternatives(sujet_template.render(sujet),
+ texte_template.render(texte),
+ 'recrutement@auf.org',
+ [candidat.email])
+ msg.attach_alternative(texte_template.render(texte_html), "text/html")
+ msg.send()
--- /dev/null
+[egg_info]
+tag_build = dev
+tag_svn_revision = true
--- /dev/null
+# -*- encoding: utf-8 -*-
+
+from setuptools import setup, find_packages
+import sys, os
+
+name = 'auf.django.emploi'
+version = '0.1'
+
+setup(name=name,
+ version=version,
+ description="Outils nécessaires pour la diffusion des offres d'emploi et \
+ la soumissions des candidatures, dans l'application de \
+ recrutement du système SGRH.",
+ long_description="""\
+""",
+ classifiers=[], # Get strings from http://pypi.python.org/pypi?%3Aaction=list_classifiers
+ keywords='',
+ author='Nilovna Bascunan-Vasquez',
+ author_email='contact@nilovna.com',
+ url='http://pypi.auf.org/%s' % name,
+ license='GPL',
+ packages=find_packages(exclude=['ez_setup', 'examples', 'tests']),
+ include_package_data=True,
+ zip_safe=False,
+ install_requires=[
+ # -*- Extra requirements: -*-
+ ],
+ entry_points="""
+ # -*- Entry points: -*-
+ """,
+ )