Script de controle de Stphane.
darcs-hash:20051102010801-41617-78943cd796f888e2e50d930f38c435427715a543.gz
This commit is contained in:
parent
cb0f4c2580
commit
f396e533c2
1 changed files with 331 additions and 0 deletions
331
admin/controle_tresorier.py
Executable file
331
admin/controle_tresorier.py
Executable file
|
@ -0,0 +1,331 @@
|
|||
#! /usr/bin/env python
|
||||
# -*- coding: iso-8859-15 -*-
|
||||
|
||||
# Copyright (C) Stéphane Glondu
|
||||
# Licence : GPLv2
|
||||
|
||||
u"""Ce script permet au trésorier de contrôler plus facilement le travail
|
||||
des câbleurs.
|
||||
|
||||
Usage: %(prog)s {paiement|carte|mail}
|
||||
|
||||
Les options sont :
|
||||
* paiement : contrôle interactif des nouvelles (ré-)adhésions
|
||||
* carte : contrôle interactif des nouvelles cartes d'étudiant
|
||||
* mails : envoyer les mails de rappel"""
|
||||
|
||||
import sys, os, re
|
||||
sys.path.append('/usr/scripts/gestion')
|
||||
|
||||
# Fonctions d'affichage
|
||||
from affich_tools import coul, tableau, prompt
|
||||
|
||||
# Importation de la base de données
|
||||
from ldap_crans import crans_ldap, ann_scol
|
||||
db = crans_ldap()
|
||||
|
||||
# Détermination de l'uid du câbleur
|
||||
from user_tests import getuser
|
||||
uid = getuser()
|
||||
if not uid :
|
||||
print u"Impossible de déterminer l'utilisateur !"
|
||||
sys.exit(1)
|
||||
cableur = db.search('uid=%s' % uid)['adherent'][0]
|
||||
|
||||
# Vérification des droits
|
||||
if u'Contrôleur' not in cableur.droits():
|
||||
print u"Il faut être contrôleur pour exécuter ce script !"
|
||||
sys.exit(1)
|
||||
|
||||
# Lors des tests sur egon, on m'envoie tous les mails !
|
||||
from socket import gethostname
|
||||
testing = gethostname().split(".")[0] == 'egon'
|
||||
if testing:
|
||||
print coul(u'Mode testing !', 'violet')
|
||||
ann_scol = 2004
|
||||
|
||||
|
||||
def _controle_interactif_adherents(liste, quoi):
|
||||
u"""
|
||||
Contrôle interactif des adhérents de la liste (quoi = p ou c).
|
||||
Retourne (nb_OK, nb_pas_OK).
|
||||
"""
|
||||
if quoi not in 'pc': raise ValueError
|
||||
explicite = {'p': u'du paiement', 'c': u"de la carte d'étudiant"}[quoi]
|
||||
restant = len(liste)
|
||||
|
||||
print coul(u'\nContrôle %s des adhérents' % explicite, 'cyan')
|
||||
print u"Pour chaque entrée, il faut taper 'o' ou 'n' (défaut=n)."
|
||||
print u"Une autre réponse entraîne l'interruption du processus."
|
||||
print u"Le format est [nb_restant] Nom, Prénom (aid)."
|
||||
print
|
||||
|
||||
nb = 0
|
||||
for a in liste:
|
||||
ok = prompt(u'[%3d] %s, %s (%s) ?'
|
||||
% (restant, a.nom(), a.prenom(), a.id()), 'n', '').lower()
|
||||
restant -= 1
|
||||
if ok == 'o':
|
||||
modifiable = db.search('aid=%s' % a.id(), 'w')['adherent'][0]
|
||||
if modifiable._modifiable:
|
||||
modifiable.controle('+%s' % quoi)
|
||||
print modifiable.save()
|
||||
nb += 1
|
||||
else:
|
||||
print coul(u'Adhérent %s locké, réessayer plus tard' % modifiable.Nom(), 'rouge')
|
||||
elif ok != 'n':
|
||||
print coul(u'Arrêt du contrôle %s des adhérents' % explicite, 'rouge')
|
||||
break
|
||||
|
||||
return nb, len(liste)-nb
|
||||
|
||||
|
||||
def _controle_interactif_clubs(liste):
|
||||
u"""
|
||||
Contrôle interactif des clubs de la liste (uniquement la charte).
|
||||
Retourne (nb_OK, nb_pas_OK).
|
||||
"""
|
||||
restant = len(liste)
|
||||
|
||||
print coul(u'\nContrôle de la charte des clubs', 'cyan')
|
||||
print u"Pour chaque entrée, il faut taper 'o' ou 'n'."
|
||||
print u"Une autre réponse entraîne l'interruption du processus."
|
||||
print u"Le format est [nb_restant] Nom (cid)."
|
||||
print
|
||||
|
||||
nb = 0
|
||||
for c in liste:
|
||||
ok = prompt(u'[%2d] %s (%s) ?'
|
||||
% (restant, c.Nom(), c.id()), 'n', '').lower()
|
||||
restant -= 1
|
||||
if ok == 'o':
|
||||
modifiable = db.search('cid=%s' % c.id(), 'w')['club'][0]
|
||||
if modifiable._modifiable:
|
||||
modifiable.controle('+p')
|
||||
print modifiable.save()
|
||||
nb += 1
|
||||
else:
|
||||
print coul(u'Club %s locké, réessayer plus tard' % modifiable.Nom(), 'rouge')
|
||||
elif ok != 'n':
|
||||
print coul(u'Arrêt du contrôle de la charte des clubs', 'rouge')
|
||||
break
|
||||
|
||||
return nb, len(liste)-nb
|
||||
|
||||
|
||||
def controle_interactif(quoi):
|
||||
u"""
|
||||
Procédure interactive de contrôle des paiements/chartes (quoi=p) et cartes (quoi=c).
|
||||
"""
|
||||
if quoi not in 'pc': raise ValueError
|
||||
todo_list = db.search('%s=%d&controle!=*%s*'
|
||||
% ({'p': 'paiement', 'c': 'carteEtudiant'}[quoi], ann_scol, quoi))
|
||||
|
||||
# Tri de la liste des adhérents selon nom, prénom
|
||||
# Ça peut se faire plus facilement en Python 2.4 avec l'argument key
|
||||
todo_list['adherent'].sort(lambda x, y: cmp((x.nom(), x.prenom()), (y.nom(), y.prenom())))
|
||||
|
||||
# Traitement des adhérents
|
||||
oka, noka = _controle_interactif_adherents(todo_list['adherent'], quoi)
|
||||
|
||||
if quoi == 'p':
|
||||
# Tri de la liste des clubs
|
||||
todo_list['club'].sort(lambda x, y: cmp(x.nom(), y.nom()))
|
||||
|
||||
# Traitement des clubs (uniquement la charte)
|
||||
okc, nokc =_controle_interactif_clubs(todo_list['club'])
|
||||
|
||||
print coul(u'\nRécapitulatif des nouveaux contrôles +%s :' % quoi, 'violet')
|
||||
liste = [(u'Catégorie', u'OK', u'pas OK'),
|
||||
(u'adhérents', str(oka), str(noka))]
|
||||
if quoi == 'p':
|
||||
liste.append((u'clubs', str(okc), str(nokc)))
|
||||
print tableau([15, 10, 10], liste)
|
||||
|
||||
|
||||
def formater_pour_cableur(liste):
|
||||
u"""
|
||||
Formate la liste d'adhérents ou de clubs avec les dates correspondantes.
|
||||
liste est une liste de couples (date, objet).
|
||||
"""
|
||||
lignes = [(u'id', u'Nom', u'Date Heure')]
|
||||
|
||||
for date, a in liste:
|
||||
lignes.append((a.id(), a.Nom(), date))
|
||||
|
||||
return tableau([6, 40, 18], lignes)
|
||||
|
||||
|
||||
def formater_pour_bureau(dico):
|
||||
u"""
|
||||
Formate la liste d'adhérents ou de clubs avec les câbleurs correspondantes
|
||||
pour le mail récapitulatif envoyé à bureau.
|
||||
"""
|
||||
lignes = [(u'id', u'Nom', u'Câbleur')]
|
||||
|
||||
total = 0
|
||||
for cableur in dico.keys():
|
||||
for date, a in dico[cableur]:
|
||||
lignes.append((a.id(), a.Nom(), cableur))
|
||||
total += 1
|
||||
|
||||
return tableau([6, 40, 17], lignes) + '\nTotal : %d' % total
|
||||
|
||||
|
||||
def qui(historique, quoi):
|
||||
u"""
|
||||
Recherche le câbleur qui a effectué la dernière modification quoi
|
||||
dans l'historique, ou qui a inscrit l'adhérent.
|
||||
Retourne le couple (date_heure, nom_cableur).
|
||||
"""
|
||||
regexp = re.compile(r'^([^,]*), ([^ :]*)')
|
||||
cableur = ('_inconnu_', '_inconnu_')
|
||||
|
||||
for ligne in historique:
|
||||
if quoi in ligne or 'inscription' in ligne:
|
||||
matched = regexp.match(ligne)
|
||||
if matched: cableur = matched.group(1), matched.group(2)
|
||||
|
||||
return cableur
|
||||
|
||||
|
||||
def chercher_cableurs(liste, quoi):
|
||||
u"""
|
||||
Renvoie un dictionnaire cableur->adherents à partir de liste, quoi
|
||||
désigne le champ qui sera recherché dans l'historique.
|
||||
"""
|
||||
resultat = {}
|
||||
|
||||
for a in liste:
|
||||
date, cableur = qui(a.historique(), quoi)
|
||||
if not resultat.has_key(cableur): resultat[cableur] = []
|
||||
resultat[cableur].append((date, a))
|
||||
|
||||
return resultat
|
||||
|
||||
|
||||
from smtplib import SMTP
|
||||
from email.MIMEText import MIMEText
|
||||
|
||||
|
||||
def envoyer_mails_rappel():
|
||||
u"""
|
||||
Envoyer les mails de rappel aux câbleurs avec bureau en cc,
|
||||
ainsi que le récapitulatif à bureau.
|
||||
"""
|
||||
# On recherche tous les câbleurs concernés
|
||||
todo_list = db.search('paiement=%d&controle!=*p*' % ann_scol)
|
||||
paiements = chercher_cableurs(todo_list['adherent'], 'paiement')
|
||||
chartes = chercher_cableurs(todo_list['club'], 'paiement')
|
||||
cartes = chercher_cableurs(db.search('carteEtudiant=%d&controle!=*c*' % ann_scol)['adherent'], 'carteEtudiant')
|
||||
|
||||
# Méthode de Vince
|
||||
cableurs = {}
|
||||
for a in paiements.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
for a in chartes.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
for a in cartes.keys():
|
||||
if a != '_inconnu_': cableurs[a] = None
|
||||
|
||||
# Squelette à modifier après
|
||||
msg_skeleton = u"""\
|
||||
Salut,
|
||||
|
||||
Tu me dois des papiers. J'ai mis l'aid ou le cid afin que tu puisses
|
||||
vérifier facilement dans la base.
|
||||
%s
|
||||
Peux-tu confirmer et donner ces papiers le plus rapidement possible à
|
||||
Florian, Augustin, les laisser au 2B ou directement me les donner ?
|
||||
|
||||
--
|
||||
Stéphane
|
||||
"""
|
||||
|
||||
# Vérification de l'alias pour l'envoi des mails
|
||||
if u'tresorier' in cableur.alias():
|
||||
moi = (u'%s <tresorier@crans.org>' % cableur.Nom()).encode('utf8')
|
||||
else:
|
||||
moi = (u'%s <%s@crans.org>' % (cableur.Nom(), cableur.canonical_alias())).encode('utf8')
|
||||
|
||||
# On se connecte au serveur
|
||||
s = SMTP()
|
||||
s.connect()
|
||||
|
||||
# On envoie les mails
|
||||
nb = 0
|
||||
for c in cableurs.keys():
|
||||
msg = u''
|
||||
|
||||
if c in paiements.keys():
|
||||
msg += u"\nFiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_cableur(paiements[c]) + '\n'
|
||||
|
||||
if c in chartes.keys():
|
||||
msg += u"\nChartes signées des clubs :\n"
|
||||
msg += formater_pour_cableur(chartes[c]) + '\n'
|
||||
|
||||
if c in cartes.keys():
|
||||
msg += u"\nCarte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_cableur(cartes[c]) + '\n'
|
||||
|
||||
mail = MIMEText((msg_skeleton % msg).encode('utf8'), _charset='UTF-8')
|
||||
mail['Subject'] = u'Papiers manquants'.encode('utf8')
|
||||
mail['From'] = moi
|
||||
adresse_cableur = '%s@crans.org' % c
|
||||
mail['To'] = adresse_cableur
|
||||
mail['Cc'] = 'Bureau <bureau@crans.org>'
|
||||
if testing:
|
||||
recipients = ['glondu@crans.org']
|
||||
else:
|
||||
recipients = [adresse_cableur, 'bureau@crans.org']
|
||||
s.sendmail(moi, recipients, mail.as_string())
|
||||
nb += 1
|
||||
|
||||
# On envoie le mail récapitulatif sur bureau
|
||||
if paiements or chartes or cartes:
|
||||
msg = u''
|
||||
|
||||
msg += u"\nFiches d'adhésion et cotisations des adhérents :\n"
|
||||
msg += formater_pour_bureau(paiements) + '\n'
|
||||
|
||||
msg += u"\nChartes signées des clubs :\n"
|
||||
msg += formater_pour_bureau(chartes) + '\n'
|
||||
|
||||
msg += u"\nCarte d'étudiant des adhérents :\n"
|
||||
msg += formater_pour_bureau(cartes) + '\n'
|
||||
|
||||
msg += u"\n-- \nScript exécuté par %s\n" % cableur.Nom()
|
||||
mail = MIMEText(msg.encode('utf8'), _charset='utf8')
|
||||
mail['Subject'] = u'Récapitulatif des papiers manquants'.encode('utf8')
|
||||
mail['From'] = moi
|
||||
mail['To'] = 'Bureau <bureau@crans.org>'
|
||||
if testing:
|
||||
recipients = ['glondu@crans.org']
|
||||
else:
|
||||
recipients = ['bureau@crans.org']
|
||||
s.sendmail(moi, recipients, mail.as_string())
|
||||
nb += 1
|
||||
|
||||
s.close()
|
||||
print coul(u"%d mail(s) envoyé(s) avec succès !" % nb, "vert")
|
||||
|
||||
|
||||
def __usage():
|
||||
u""" Comment ça marche ? """
|
||||
print __doc__ % {'prog': sys.argv[0]}
|
||||
sys.exit(1)
|
||||
|
||||
if __name__ == '__main__' :
|
||||
if len(sys.argv) == 2:
|
||||
if sys.argv[1] == 'paiement':
|
||||
controle_interactif('p')
|
||||
elif sys.argv[1] == 'carte':
|
||||
controle_interactif('c')
|
||||
elif sys.argv[1] == 'mail':
|
||||
envoyer_mails_rappel()
|
||||
else:
|
||||
__usage()
|
||||
else:
|
||||
__usage()
|
||||
sys.exit(0)
|
Loading…
Add table
Add a link
Reference in a new issue