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