Passage aux adhésions glissantes (partie I, sans lc_ldap)

This commit is contained in:
Pierre-Elliott Bécue 2014-08-15 20:26:12 +02:00
parent 169b7000b8
commit 49cef4c095
12 changed files with 485 additions and 231 deletions

View file

@ -40,7 +40,6 @@ import time
db = crans_ldap() db = crans_ldap()
date_debut_ann_scol = time.mktime((ann_scol, 8, 1, 0, 0, 0, 0, 0, 0)) date_debut_ann_scol = time.mktime((ann_scol, 8, 1, 0, 0, 0, 0, 0, 0))
paiement_ann_scol = "paiement+%d" % ann_scol
def datestrtoint(strdate): def datestrtoint(strdate):
u""" Convertit une date en entier. """ u""" Convertit une date en entier. """

View file

@ -18,7 +18,7 @@ def _need_conn(f):
if __name__.endswith('annuaires_pg_test'): if __name__.endswith('annuaires_pg_test'):
host='localhost' host='localhost'
else: else:
host='pgsql.adm.crans.org' host='pgsql.v4.adm.crans.org'
# "connecting …" # "connecting …"
try: try:
if not conn: if not conn:

View file

@ -13,6 +13,7 @@ import datetime
import time import time
import re import re
import lc_ldap.shortcuts import lc_ldap.shortcuts
from lc_ldap.crans_utils import fromGeneralizedTimeFormat, toGeneralizedTimeFormat
conn = lc_ldap.shortcuts.lc_ldap_admin() conn = lc_ldap.shortcuts.lc_ldap_admin()
import mail as mail_module import mail as mail_module
@ -38,12 +39,11 @@ year = config.ann_scol
delai = config.demenagement_delai delai = config.demenagement_delai
# On récupère ceux qui n'ont pas payé cette année # On récupère ceux qui n'ont pas payé cette année
if config.periode_transitoire:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(paiement=%d)(!(paiement=%d)))' % (year-1,year))
else:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(paiement=%d))' % year)
now = time.time() now = time.time()
if config.periode_transitoire:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(|(&(paiement=%d)(!(paiement=%d)))(finAdhesion<=%s)(finConnexion<=%s)))' % (year-1, year, toGeneralizedTimeFormat(now), toGeneralizedTimeFormat(now)))
else:
bad_boys_e_s = conn.search(u'(&(aid=*)(chbre=????)(|(paiement=%d)(finAdhesion>=%s)(finConnexion>=%s)))' % (year, toGeneralizedTimeFormat(now), toGeneralizedTimeFormat(now)))
to_print = [] to_print = []
to_error = [] to_error = []

View file

@ -30,7 +30,8 @@ else:
ann_scol = dat[0] ann_scol = dat[0]
periode_transitoire = False periode_transitoire = False
duree_periode_transitoire = 45*86400 debut_periode_transitoire = time.mktime(time.strptime("%s/08/16 00:00:00" % (ann_scol,), "%Y/%m/%d %H:%M:%S"))
fin_periode_transitoire = time.mktime(time.strptime("%s/09/30 23:59:59" % (ann_scol,), "%Y/%m/%d %H:%M:%S"))
## Bloquage si carte d'étudiants manquante pour l'année en cours ## Bloquage si carte d'étudiants manquante pour l'année en cours
# /!\ Par sécurité, ces valeurs sont considérées comme False si # /!\ Par sécurité, ces valeurs sont considérées comme False si

View file

@ -21,19 +21,25 @@ Retournent None si pas d'objet trouvé.
# Destinataires, si vide n'envoi rien # Destinataires, si vide n'envoi rien
To = ['root@crans.org'] To = ['root@crans.org']
import string, os, sys import string
import os
import sys
import dialog import dialog
from whos import aff from whos import aff
import signal, getopt import signal
from time import strftime, strptime, localtime, mktime import getopt
from time import strftime, strptime, localtime, mktime, time
import re import re
import affich_tools, config import affich_tools
import config
import config.cotisation as cotisation
from affich_tools import cprint, to_encoding, to_unicode from affich_tools import cprint, to_encoding, to_unicode
from lock import make_lock, remove_lock from lock import make_lock, remove_lock
from ldap_crans import crans_ldap, blacklist_items, ann_scol, droits_possibles, droits_critiques, smtpserv, script_utilisateur from ldap_crans import crans_ldap, blacklist_items, ann_scol, droits_possibles, droits_critiques, smtpserv, script_utilisateur
from ldap_crans import Adherent, AssociationCrans, Club, Facture from ldap_crans import Adherent, AssociationCrans, Club, Facture
from ldap_crans import Machine, MachineFixe, MachineWifi, MachineCrans, BorneWifi from ldap_crans import Machine, MachineFixe, MachineWifi, MachineCrans, BorneWifi
from ldap_crans import tz, generalizedTimeFormat, fromGeneralizedTimeFormat
import user_tests import user_tests
isadm = user_tests.isadm() isadm = user_tests.isadm()
@ -61,7 +67,7 @@ else:
def dialog(arg): def dialog(arg):
return affich_tools.dialog(u'Gestion des adhérents et machines du Crans', arg, dialog_theme) return affich_tools.dialog(u'Gestion des adhérents et machines du Crans', arg, dialog_theme)
in_facture = None
######################################################################### #########################################################################
## Fonctions de remplissage ou modification des paramètres d'un adhérent ## Fonctions de remplissage ou modification des paramètres d'un adhérent
@ -717,7 +723,6 @@ def del_adher(adher):
arg += u'--msgbox "Machines détruites\n\n\n" 0 0' arg += u'--msgbox "Machines détruites\n\n\n" 0 0'
dialog(arg) dialog(arg)
return return
del(machines)
while 1: while 1:
arg = u'--title "Destruction adhérent %s " --colors ' % adher.Nom() arg = u'--title "Destruction adhérent %s " --colors ' % adher.Nom()
@ -1125,9 +1130,12 @@ def set_vente(proprio):
def confirm(clas): def confirm(clas):
u""" Demande confirmation avant enregistrement""" u""" Demande confirmation avant enregistrement"""
global in_facture
# On va faire en texte, les couleurs ne passent pas en curses # On va faire en texte, les couleurs ne passent pas en curses
os.system('clear') os.system('clear')
aff(clas) aff(clas)
if in_facture is not None:
cprint("Une facture d'un montant total de %s € sera confirmée." % (in_facture.total()), "rouge")
while 1: while 1:
r = affich_tools.prompt(u"Valider et enregister ? [O/N]") r = affich_tools.prompt(u"Valider et enregister ? [O/N]")
if r == 'O' or r == 'o': if r == 'O' or r == 'o':
@ -1136,11 +1144,15 @@ def confirm(clas):
return 1 return 1
try: try:
res = clas.save() res = clas.save()
except (EnvironmentError, RuntimeError) as c: if in_facture is not None:
in_facture.recuPaiement(strftime("%Y-%m-%d %H:%M:%S"))
in_facture.save()
except Exception as c:
arg = u'--title "Enregistrement" ' arg = u'--title "Enregistrement" '
arg += u'--msgbox "%s\n\n\n" 0 0' % to_unicode(c.args[0]) arg += u'--msgbox "%s\n\n\n" 0 0' % to_unicode(c.args[0])
dialog(arg) dialog(arg)
return 1 return 1
in_facture = None
cprint(res) cprint(res)
affich_tools.prompt(u"Appuyez sur ENTREE pour continuer") affich_tools.prompt(u"Appuyez sur ENTREE pour continuer")
@ -1288,11 +1300,7 @@ def set_admin(proprio):
has_card = proprio.idn != 'cid' has_card = proprio.idn != 'cid'
# Initialisation des différentes checkbox # Initialisation des différentes checkbox
carte = on_off(ann_scol in proprio.carteEtudiant()) carte = on_off(proprio.carteEtudiant())
prev_carte = on_off(ann_scol - 1 in proprio.carteEtudiant())
paiement = on_off(ann_scol in proprio.paiement())
prev_paiement = on_off(ann_scol - 1 in proprio.paiement())
paiement_ok = on_off('p' in proprio.controle())
carte_ok = on_off('c' in proprio.controle()) carte_ok = on_off('c' in proprio.controle())
if has_card: charte_MA = on_off(proprio.charteMA()) if has_card: charte_MA = on_off(proprio.charteMA())
@ -1302,35 +1310,17 @@ def set_admin(proprio):
if has_card: if has_card:
if carte_ok == 'off' or iscontroleur: if carte_ok == 'off' or iscontroleur:
checklist.append(u'"1" "Carte d\'étudiant %d/%d fournie" "%s"' % checklist.append(u'"1" "Carte d\'étudiant fournie" "%s"' %
(ann_scol, ann_scol+1, carte)) (carte,))
else: else:
texte.append(u'Carte vérifiée') texte.append(u'Carte vérifiée')
if isinstance(proprio, Club) or proprio.adherentPayant():
if paiement_ok == 'off' or iscontroleur:
checklist.append(u'"2" "Cotisation %d/%d réglée et charte signée" "%s"' %
(ann_scol, ann_scol+1, paiement))
else:
texte.append(u'Cotisation/charte vérifiées')
else:
texte.append(u'Adhérent non payant')
if iscontroleur: if iscontroleur:
if has_card: if has_card:
checklist.append(u'"4" "Carte d\'étudiant vérifiée" "%s"' % carte_ok) checklist.append(u'"2" "Carte d\'étudiant vérifiée" "%s"' % carte_ok)
checklist.append(u'"5" "Cotisation/charte vérifiées" "%s"' % paiement_ok)
# Carte et paiement de l'année précédente # Carte et paiement de l'année précédente
if has_card:
checklist.append(u'"6" "Carte d\'étudiant %d/%d fournie" "%s"' %
(ann_scol - 1, ann_scol, prev_carte))
if isinstance(proprio, Club) or proprio.adherentPayant():
checklist.append(u'"7" "Cotisation %d/%d réglée et charte signée" "%s"' %
(ann_scol - 1, ann_scol, prev_paiement))
if (isbureau or isadm) and has_card: if (isbureau or isadm) and has_card:
checklist.append(u'"8" "Charte des MA signee" "%s"' % charte_MA) checklist.append(u'"3" "Charte des MA signee" "%s"' % charte_MA)
if not checklist: if not checklist:
# Il n'y a rien de modifiable # Il n'y a rien de modifiable
@ -1351,71 +1341,189 @@ def set_admin(proprio):
# Traitement # Traitement
if has_card: if has_card:
if '1\n' in result: if '1\n' in result:
proprio.carteEtudiant(ann_scol) proprio.carteEtudiant(True)
elif iscontroleur or carte_ok == 'off': elif iscontroleur or carte_ok == 'off':
proprio.carteEtudiant(-ann_scol) proprio.carteEtudiant(False)
if iscontroleur: if '2\n' in result:
if '6\n' in result:
proprio.carteEtudiant(ann_scol - 1)
else:
proprio.carteEtudiant(-(ann_scol - 1))
if '4\n' in result:
proprio.controle('+c') proprio.controle('+c')
else: else:
proprio.controle('-c') proprio.controle('-c')
if '2\n' in result and ann_scol not in proprio.paiement():
# On est en train de renouveller l'adhésion
# Combien a-t-il de machines ?
if proprio.idn != 'cid' and len(proprio.machines_fixes()) > 1 and not proprio.droits():
# Il a plus d'une machine fixe et n'est pas membre actif
arg = u'--title "Trop de machines fixes" '
arg += u'--menu " Cet adhérent a trop de machines fixes.\n\n'
arg += u'Seuls les membres actifs peuvent posséder plusieurs\n'
arg += u'machines fixes. L\'adhérent actuel n\'est pas membre\n'
arg += u'actif, il n\'est donc pas possible de lui laisser autant\n'
arg += u'de machines fixes..." 0 0 0 '
arg += u'"OK" "OK, je vais lui virer des machines" '
annul, result = dialog(arg)
if not annul and result[0] == "Si":
proprio.paiement(ann_scol)
else:
set_admin(proprio)
return
else:
proprio.paiement(ann_scol)
elif '2\n' not in result and (paiement_ok == 'off' or iscontroleur):
proprio.paiement(-ann_scol)
if iscontroleur:
if '7\n' in result:
proprio.paiement(ann_scol - 1)
else:
proprio.paiement(-(ann_scol - 1))
if '3\n' in result:
proprio.paiement(ann_scol+1)
elif paiement_ok == 'off' or iscontroleur:
proprio.paiement(-ann_scol-1)
if '5\n' in result:
proprio.controle('+p')
elif iscontroleur:
proprio.controle('-p')
if has_card: if has_card:
if '8\n' in result: if '3\n' in result:
proprio.charteMA(True) proprio.charteMA(True)
elif isadm or isbureau: elif isadm or isbureau:
proprio.charteMA(False) proprio.charteMA(False)
if 'C\n' in result: def set_adhesion(proprio):
proprio.controle('+k') """Maj de la période d'accès de l'adhérent"""
if not iscontroleur: global in_facture
proprio.controle('-p')
elif iscontroleur: end = proprio.adhesion()
proprio.controle('-k') annul = 0
args = u'--title "Adhésion de %s" ' % proprio.Nom()
if end and end - cotisation.delai_readh > time():
t_end = strftime('%d/%m/%Y %H:%M:%S', localtime(end))
args += u'--msgbox "Actuellement adhérent jusqu\'au %s.\nMerci de revenir lorsqu\'il restera moins de %s jours avant la fin." 0 0 ' % (t_end, cotisation.delai_readh_jour,)
dialog(args)
return 1
elif end and end - cotisation.delai_readh <= time():
t_end = strftime('%d/%m/%Y %H:%M:%S', localtime(end))
args += u'--yesno "Adhésion jusqu\'au %s. Réadhérer ?" 0 0 ' %(t_end,)
annul, res = dialog(args)
else:
args += u'--yesno "Adhésion pour un an, continuer ?" 0 0 '
annul, res = dialog(args)
if annul:
return 1
if in_facture is not None:
f = in_facture
else:
f = None
facture = proprio.adhesion(True, f)
if float(facture.total()) == 0.0:
facture.modePaiement('liquide')
while True and not facture.modePaiement():
arg = u'--title "Mode de paiement pour l\'adhésion de %s" ' % (proprio.Nom(),)
arg += u'--menu "Comment %s souhaite-t-il payer ?" 0 0 0 ' % (proprio.Nom(), )
arg += u'"Liquide" "En espèces : penser à mettre l\'argent dans une enveloppe." '
arg += u'"Cheque" "Par chèque : ne pas oublier de vérifier signature, date, ordre et montant." '
if proprio.solde() - facture.total() > 0:
arg += u'"Solde" "Par solde : il a assez d\'argent pour ça." '
annul, res = dialog(arg)
if annul:
facture._set('finAdhesion', [])
facture._set('debutAdhesion', [])
facture.supprime(pop=True)
return 1
res = res[0]
if res == "Liquide" or res == "Cheque":
arg = u'--title "Avertissement" '
arg += u'--msgbox "Une facture sera créée, après validation par le trésorier, l\'adhérent\npourra y accéder via l\'intranet ou la demander." 0 0'
dialog(arg)
facture.modePaiement(res.lower())
break
else:
facture.modePaiement(res.lower())
break
in_facture = facture
def set_connexion(proprio):
"""Maj de la période d'accès de l'adhérent"""
global in_facture
# Si l'adhérent ne l'est plus, on commence par le faire adhérer, sauf s'il a une facture adhésion.
adhEnd = proprio.adhesion()
if in_facture is not None:
adhEnd = max(adhEnd, fromGeneralizedTimeFormat(in_facture._data.get('finAdhesion', ["19700101000000Z"])[0]))
if adhEnd < time():
stat = set_adhesion(proprio)
if stat == 1:
return 1
end = proprio.connexion()
args = u'--title "Connexion de %s" ' % proprio.Nom()
if end > adhEnd:
args += u'--msgbox "La fin de l\'adhésion arrivera avant le début de cette connexion.\nIl faudra d\'abord réadhérer." 0 0 ' % (t_end, cotisation.delai_readh_jour,)
dialog(args)
return 1
while True:
while True:
args = u'--title "Connexion de %s" ' % proprio.Nom()
if proprio.connexion() > time():
args += u'--menu "Connexion jusqu\'au %s, choisir une durée de prolongation. : " 0 0 0 ' % (strftime("%d/%m/%Y %H:%M:%S"),)
else:
args += u'--menu "Connexion actuellement inactive, choisir une durée. : " 0 0 0 '
args += u'"An" "Prolonger d\'un an." '
args += u'"Select" "Prolonger de plusieurs mois." '
args += u'"Mois" "Prolonger d\'un mois." '
annul, res = dialog(args)
if annul:
in_facture.supprime(pop=True)
return 1
res = res[0]
if res == "An":
nb_mois = 12
break
elif res == "Select":
back = False
while True:
arg = u'--title "Nombre de mois de connexion ? (entre 2 et 12)" '
arg += u'--inputbox "" 0 0 "1" '
annul, res = dialog(arg)
if annul:
back = True
break
else:
try:
res = int(res[0])
except:
arg = u'--title "Opération impossible" '
arg += u'--msgbox "On a dit un entier…" 0 0'
dialog(arg)
continue
if res < 2 or res > 12:
arg = u'--title "Opération impossible" '
arg += u'--msgbox "On a dit un entier entre 2 et 12." 0 0'
dialog(arg)
continue
else:
nb_mois = res
break
if back:
continue
break
else:
nb_mois = 1
break
if in_facture is not None:
f = in_facture
else:
f = None
facture = proprio.connexion(nb_mois, f)
newEnd = fromGeneralizedTimeFormat(facture._data.get('finConnexion', ["19700101000000Z"])[0])
if newEnd > adhEnd and newEnd - adhEnd >= (cotisation.duree_conn_max - cotisation.duree_conn_plafond)*30*86400:
arg = u'--title "Avertissement" '
arg += u'--yesno "La fin de la connexion de l\'adhérent (%s) tombera après la fin de son adhésion (%s).\nS\'il veut en profiter, il lui faudra réadhérer. Continuer ?" 0 0' %(strftime('%d/%m/%Y %H:%M:%S', localtime(newEnd)), strftime('%d/%m/%Y %H:%M:%S', localtime(adhEnd)), )
no, res = dialog(arg)
if no:
facture._set('finConnexion', [])
facture._set('debutConnexion', [])
facture.supprime(pop=True)
continue
if not f.modePaiement():
arg = u'--title "Mode de paiement pour la connexion de %s" ' % (proprio.Nom(),)
arg += u'--menu "Comment %s souhaite-t-il payer ?" 0 0 0 ' % (proprio.Nom(), )
arg += u'"Liquide" "En espèces : penser à mettre l\'argent dans une enveloppe." '
arg += u'"Cheque" "Par chèque : ne pas oublier de vérifier signature, date, ordre et montant." '
if proprio.solde() - facture.total() > 0:
arg += u'"Solde" "Par solde : il a assez d\'argent pour ça." '
annul, res = dialog(arg)
if annul:
facture._set('finConnexion', [])
facture._set('debutConnexion', [])
facture.supprime(pop=True)
continue
res = res[0]
if res == "Liquide" or res == "Cheque":
arg = u'--title "Avertissement" '
arg += u'--msgbox "Une facture sera créée, après validation par le trésorier, l\'adhérent\npourra y accéder via l\'intranet ou la demander." 0 0'
dialog(arg)
facture.modePaiement(res.lower())
break
else:
facture.modePaiement(res.lower())
break
in_facture = facture
############################################################### ###############################################################
## Fonctions de remplissage ou modification des paramètres club ## Fonctions de remplissage ou modification des paramètres club
@ -1441,7 +1549,7 @@ def new_club(club):
if step == 4: if step == 4:
# Administratif # Administratif
if set_admin(club): step -= 1 if set_adhesion(club): step -= 1
else: step += 1 else: step += 1
if step == 5: if step == 5:
@ -1459,12 +1567,15 @@ def modif_club(club):
Modification du club fourni (instance de club) Modification du club fourni (instance de club)
Retourne 1 si annulation. Retourne 1 si annulation.
""" """
global in_facture
arg = u'--title "Modification du club %s" ' % club.Nom() arg = u'--title "Modification du club %s" ' % club.Nom()
arg += u'--menu "Que souhaitez vous modifier ?" 0 0 0 ' arg += u'--menu "Que souhaitez vous modifier ?" 0 0 0 '
arg += u'"NomClub" "Modifier le nom du club" ' arg += u'"NomClub" "Modifier le nom du club" '
arg += u'"Responsable" "Changer le responsable du club %s" ' % club.responsable().Nom() arg += u'"Responsable" "Changer le responsable du club %s" ' % club.responsable().Nom()
arg += u'"Imprimeurs" "Changer la liste des imprimeurs" ' arg += u'"Imprimeurs" "Changer la liste des imprimeurs" '
arg += u'"Administratif" "Précâblage" ' arg += u'"Administratif" "Données administratives" '
arg += u'"Adhesion" "Pour les réadhésions" '
arg += u'"Local" "Modifier le local du club" ' arg += u'"Local" "Modifier le local du club" '
arg += u'"Compte" "Créer un compte crans." ' arg += u'"Compte" "Créer un compte crans." '
if club.compte(): if club.compte():
@ -1485,8 +1596,8 @@ def modif_club(club):
set_responsable(club) set_responsable(club)
elif res[0] == 'Imprimeurs': elif res[0] == 'Imprimeurs':
set_imprimeurs(club) set_imprimeurs(club)
elif res[0] == 'Administratif': elif res[0] == 'Adhesion':
set_admin(club) set_adhesion(club)
elif res[0] == 'Compte': elif res[0] == 'Compte':
set_club_compte(club) set_club_compte(club)
elif res[0] == 'Remarque': elif res[0] == 'Remarque':
@ -1811,7 +1922,8 @@ def new_adher(adher):
if set_bases(adher): return 1 if set_bases(adher): return 1
steps = [set_etudes, steps = [set_etudes,
#set_type_de_connexion, # Plus de connexion gratuite. Les adhérents sont payant par défaut set_adhesion,
set_connexion,
set_admin, set_admin,
set_mail, set_mail,
set_rque] set_rque]
@ -1828,6 +1940,8 @@ def modif_adher(adher):
Modification de l'adhérent fourni (instance de adhérent) Modification de l'adhérent fourni (instance de adhérent)
Retourne 1 si annulation. Retourne 1 si annulation.
""" """
global in_facture
# Préliminaire : si la chambre est inconnue on force la question # Préliminaire : si la chambre est inconnue on force la question
if adher.chbre() == '????': if adher.chbre() == '????':
res= ['Chambre'] res= ['Chambre']
@ -1845,8 +1959,8 @@ def modif_adher(adher):
arg = u'--title "Modification de %s" ' % adher.Nom() arg = u'--title "Modification de %s" ' % adher.Nom()
arg += u'--menu "Que souhaitez vous modifier ?" 0 0 0 ' arg += u'--menu "Que souhaitez vous modifier ?" 0 0 0 '
arg += u'"Administratif" "Précâblage, carte d\'étudiant, études" ' arg += u'"Administratif" "Précâblage, carte d\'étudiant, études" '
if not payant: arg += u'"Adhesion" "Pour toute réadhésion" '
arg += u'"Connexion" "Changer de type de connexion(gratuit->payant)" ' arg += u'"Connexion" "Mise à jour de l\'accès Internet" '
arg += u'"Etat-civil" "Nom, prénom" ' arg += u'"Etat-civil" "Nom, prénom" '
if adher.chbre() == 'EXT': if adher.chbre() == 'EXT':
arg += u'"Adresse" "Déménagement" ' arg += u'"Adresse" "Déménagement" '
@ -1881,8 +1995,7 @@ def modif_adher(adher):
elif res[0] == 'Etat-civil': elif res[0] == 'Etat-civil':
set_etat_civil(adher) set_etat_civil(adher)
elif res[0] == 'Administratif': elif res[0] == 'Administratif':
if not set_admin(adher): set_admin(adher)
set_etudes(adher)
elif res[0] == 'Mail': elif res[0] == 'Mail':
set_mail(adher) set_mail(adher)
elif res[0] == 'Remarque': elif res[0] == 'Remarque':
@ -1891,14 +2004,10 @@ def modif_adher(adher):
set_droits(adher) set_droits(adher)
elif res[0] == 'Blackliste': elif res[0] == 'Blackliste':
set_blackliste(adher) set_blackliste(adher)
elif res[0] == 'Charte des MA' : elif res[0] == 'Adhesion':
set_charte_MA(adher) set_adhesion(adher)
elif res[0] == 'Connexion': elif res[0] == 'Connexion':
if dlg.yesno(u"Passer à un compte payant ?") == 0: set_connexion(adher)
# On attribue une ip à toute les machines
for m in adher.machines():
m.ip("<automatique>")
adher.adherentPayant(True)
elif res[0] == 'Adresse' or res[0] == 'Chambre': elif res[0] == 'Adresse' or res[0] == 'Chambre':
arg = u'--title "Déménagement de %s" ' % adher.Nom() arg = u'--title "Déménagement de %s" ' % adher.Nom()
arg += u'--menu "Question :" 0 0 0 ' arg += u'--menu "Question :" 0 0 0 '
@ -2003,7 +2112,7 @@ def modif_adher(adher):
elif res[0] == 'Vente': elif res[0] == 'Vente':
set_vente(adher) set_vente(adher)
if adher.modifs: if adher.modifs or in_facture is not None:
return confirm(adher) return confirm(adher)
def modif_machine(machine): def modif_machine(machine):
@ -2344,6 +2453,7 @@ def menu_principal():
if not proprio: continue if not proprio: continue
if del_adher(proprio): continue if del_adher(proprio): continue
del(proprio) ; proprio= None del(proprio) ; proprio= None
del(becane) ; becane= None
elif choix == 'dM': elif choix == 'dM':
# Destruction machine # Destruction machine
@ -2533,7 +2643,7 @@ if __name__ == '__main__':
sys.stderr = sys.__stderr__ sys.stderr = sys.__stderr__
traceback = s.getvalue() traceback = s.getvalue()
try: try:
if To: if not debug and To:
# Paramètres pour le mail # Paramètres pour le mail
From = script_utilisateur + '@crans.org' From = script_utilisateur + '@crans.org'

View file

@ -17,6 +17,7 @@ import os
import random import random
import string import string
import time import time
import datetime
import sys import sys
import pwd import pwd
import errno import errno
@ -25,15 +26,17 @@ import ldap.modlist
import ldap_passwd import ldap_passwd
import netaddr import netaddr
import time
import annuaires_pg as annuaires import annuaires_pg as annuaires
import config import config
import config.impression import config.impression
import config.cotisation as cotisation
import iptools import iptools
import ip6tools import ip6tools
import cPickle import cPickle
import config_mail import config_mail
from chgpass import change_password from chgpass import change_password
from calendar import monthrange
from affich_tools import coul, prompt, cprint from affich_tools import coul, prompt, cprint
from email_tools import send_email from email_tools import send_email
from syslog import openlog, closelog, syslog from syslog import openlog, closelog, syslog
@ -151,6 +154,27 @@ def decode(s):
else: else:
return s.decode('utf-8', 'ignore') # On ignore les erreurs return s.decode('utf-8', 'ignore') # On ignore les erreurs
def tz(thetz):
abstz = 100*abs(thetz)
if thetz == 0:
return "Z"
else:
return "%s%04d" % ("+"*(thetz < 0) + "-"*(thetz > 0), abstz)
def generalizedTimeFormat(stamp):
"""Converts a timestamp (local) in a generalized time format
for LDAP
"""
return "%s%s" % (time.strftime("%Y%m%d%H%M%S", time.localtime(stamp)), tz(time.altzone/3600))
def fromGeneralizedTimeFormat(gtf):
"""Converts a GTF stamp to unix timestamp
"""
return time.mktime(time.strptime(gtf.split("-", 1)[0].split("+", 1)[0].split('Z', 1)[0], "%Y%m%d%H%M%S"))
def strip_accents(a, sois_un_porc_avec_les_espaces = True): def strip_accents(a, sois_un_porc_avec_les_espaces = True):
""" Supression des accents de la chaîne fournie """ """ Supression des accents de la chaîne fournie """
res = normalize('NFKD', decode(a)).encode('ASCII', 'ignore') res = normalize('NFKD', decode(a)).encode('ASCII', 'ignore')
@ -392,7 +416,8 @@ class CransLdap:
'historique', 'blacklist', 'droits', 'uidNumber', 'info', 'historique', 'blacklist', 'droits', 'uidNumber', 'info',
'solde', 'controle', 'contourneGreylist', 'rewriteMailHeaders', 'solde', 'controle', 'contourneGreylist', 'rewriteMailHeaders',
'ablacklist', 'homepageAlias', 'charteMA', 'ablacklist', 'homepageAlias', 'charteMA',
'adherentPayant', 'gpgFingerprint'], \ 'adherentPayant', 'gpgFingerprint', 'debutConnexion', 'finConnexion',
'debutAdhesion', 'finAdhesion'], \
'club': \ 'club': \
['cid', 'responsable', 'paiement', 'historique', 'blacklist', ['cid', 'responsable', 'paiement', 'historique', 'blacklist',
'mailAlias', 'info', 'controle', 'ablacklist', 'imprimeurClub'], \ 'mailAlias', 'info', 'controle', 'ablacklist', 'imprimeurClub'], \
@ -401,7 +426,7 @@ class CransLdap:
'borneWifi': non_auto_search_machines_champs + \ 'borneWifi': non_auto_search_machines_champs + \
['prise', 'puissance', 'canal', 'hotspot', 'positionBorne', 'nvram'], ['prise', 'puissance', 'canal', 'hotspot', 'positionBorne', 'nvram'],
'machineWifi': non_auto_search_machines_champs + ['ipsec'], 'machineWifi': non_auto_search_machines_champs + ['ipsec'],
'facture': ['fid']} 'facture': ['fid', 'debutConnexion', 'finConnexion', 'debutAdhesion', 'finAdhesion']}
# tous les champs de recherche # tous les champs de recherche
search_champs = {} search_champs = {}
@ -691,7 +716,6 @@ class CransLdap:
except: except:
raise ValueError(u"Impossible de créer l'objet %s" % nom_classe) raise ValueError(u"Impossible de créer l'objet %s" % nom_classe)
def search(self, expression, mode=''): def search(self, expression, mode=''):
""" """
Recherche dans la base LDAP, expression est une chaîne : Recherche dans la base LDAP, expression est une chaîne :
@ -757,13 +781,13 @@ class CransLdap:
# définifif (cf config.py). # définifif (cf config.py).
if config.periode_transitoire: if config.periode_transitoire:
# Pour la période transitoire année précédente ok # Pour la période transitoire année précédente ok
el = "(|(paiement=%d)(paiement=%d))" % (ann_scol, ann_scol-1) el = "(|(paiement=%d)(paiement=%d)(finAdhesion>=%s))" % (ann_scol, ann_scol-1, generalizedTimeFormat(time.time()))
else: else:
el = "(paiement=%s)" % ann_scol el = "(|(paiement=%s)(finAdhesion>=%s))" % (ann_scol, generalizedTimeFormat(time.time()))
# Doit-on bloquer en cas de manque de la carte d'etudiant ? # Doit-on bloquer en cas de manque de la carte d'etudiant ?
# (si période transitoire on ne bloque dans aucun cas) # (si période transitoire on ne bloque dans aucun cas)
if config.bl_carte_et_definitif: if config.bl_carte_et_definitif:
el = "(&(|(carteEtudiant=%d)(objectClass=club))%s)" % (ann_scol, el) el = "(&(|(carteEtudiant=%d)(objectClass=club)(carteEtudiant=TRUE))%s)" % (ann_scol, el)
elif champ[1:] == 'blacklist': elif champ[1:] == 'blacklist':
el = '(blacklist=%s)' % expr el = '(blacklist=%s)' % expr
else: else:
@ -1029,9 +1053,9 @@ class BaseClasseCrans(CransLdap):
# Il faut aussi regarder la blackliste du propriétaire # Il faut aussi regarder la blackliste du propriétaire
p = self.proprietaire() p = self.proprietaire()
bl_liste += p.blacklist() bl_liste += p.blacklist()
elif isinstance(self, Adherent) and (config.ann_scol in self.paiement()): elif isinstance(self, Adherent) and (config.ann_scol in self.paiement() or (self.adhesion() > time.time() and self.connexion() > time.time())):
# blacklistes virtuelle si on est un adhérent pour carte étudiant et chambre invalides # blacklistes virtuelle si on est un adhérent pour carte étudiant et chambre invalides
if not config.periode_transitoire and config.bl_carte_et_actif and not (config.ann_scol in self.carteEtudiant()) and not self.sursis_carte(): if not config.periode_transitoire and config.bl_carte_et_actif and not bool(self.carteEtudiant()) and not self.sursis_carte():
actifs['carte_etudiant']=('-','-') actifs['carte_etudiant']=('-','-')
if self.chbre() == '????': if self.chbre() == '????':
actifs['chambre_invalide']=('-','-') actifs['chambre_invalide']=('-','-')
@ -1144,9 +1168,7 @@ class BaseClasseCrans(CransLdap):
[ index de la remarque à modifier, nouvelle remarque ] [ index de la remarque à modifier, nouvelle remarque ]
l'index est celui obtenu dans la liste retournée par info() l'index est celui obtenu dans la liste retournée par info()
""" """
if not self._data.has_key('info'): liste = list(self._data.get('info', []))
self._data['info'] = []
liste = list(self._data['info'])
if new == None: return map(decode, liste) if new == None: return map(decode, liste)
if type(new) == list: if type(new) == list:
@ -1180,7 +1202,11 @@ class BaseClasseCrans(CransLdap):
return [] return []
if not self.dn: if not self.dn:
# Enregistrement à placer en tête de base # Enregistrement à placer en tête de base sauf si
# facture.
if isinstance(self, Facture):
self.dn = self.proprietaire().dn
else:
self.dn = self.base_dn self.dn = self.base_dn
# Construction de l'historique # Construction de l'historique
@ -1209,7 +1235,8 @@ class BaseClasseCrans(CransLdap):
'puissance', 'canal', 'prise', 'responsable', 'puissance', 'canal', 'prise', 'responsable',
'macAddress', 'ipHostNumber', 'ip6HostNumber', 'macAddress', 'ipHostNumber', 'ip6HostNumber',
'host', 'positionBorne', 'derniereConnexion', 'host', 'positionBorne', 'derniereConnexion',
'hotspot', 'dnsIpv6', 'machineAlias']: 'hotspot', 'dnsIpv6', 'machineAlias', 'finAdhesion',
'finConnexion', 'debutConnexion', 'debutAdhesion']:
if champ in self.modifs: if champ in self.modifs:
if champ not in self._init_data.keys(): if champ not in self._init_data.keys():
valeur_initiale = 'N/A' valeur_initiale = 'N/A'
@ -1227,7 +1254,9 @@ class BaseClasseCrans(CransLdap):
for champ in ['droits', 'controle', 'paiement', 'carteEtudiant', for champ in ['droits', 'controle', 'paiement', 'carteEtudiant',
'mailAlias', 'hostAlias', 'exempt', 'nvram', 'mailAlias', 'hostAlias', 'exempt', 'nvram',
'portTCPin', 'portTCPout', 'portUDPin', 'portUDPout', 'portTCPin', 'portTCPout', 'portUDPin', 'portUDPout',
'homepageAlias', 'imprimeurClub', 'gpgFingerprint']: 'homepageAlias', 'imprimeurClub', 'gpgFingerprint',
'debutConnexion', 'finConnexion', 'debutAdhesion',
'finAdhesion']:
if champ in self.modifs: if champ in self.modifs:
if champ == 'controle': if champ == 'controle':
# Ce n'est pas pareil que self._init_data.get('controle', ['']) # Ce n'est pas pareil que self._init_data.get('controle', [''])
@ -1461,6 +1490,46 @@ class BaseProprietaire(BaseClasseCrans):
self._init_data = {} self._init_data = {}
self._modifiable = 'w' self._modifiable = 'w'
def adhesion(self, update=False, f=None):
"""
Gestion de l'adhésion d'un adhérent
La durée d'adhésion ne peut être choisie
* Si update vaut True, on ajoute un an
* f est une facture passée en référence.
"""
thetime = time.time()
# On récupère sur les factures l'ensemble de celles comportant une adhésion.
adh_factures = self.factures_adh()
finAdh = max([0.0] + [fromGeneralizedTimeFormat(facture._data.get('finAdhesion', ["19700101000000Z"])[0]) for facture in adh_factures if facture.controle() != "FALSE"])
if update == False:
return finAdh
else:
ftime = datetime.datetime.fromtimestamp(max(finAdh, thetime))
if not finAdh - thetime < cotisation.delai_readh:
raise EnvironmentError, u"On ne peut réadhérer que 15 jours avant l'expiration de l'adhésion précédente."
# Calcul de la nouvelle date de fin d'adhésion.
# le +86400 est une souplesse pour permettre au câblage de se passer sans warning
# quand le mec se fait câbler pour un an.
newFinAdh = time.mktime(ftime.replace(year=ftime.year + cotisation.duree_adh_an).timetuple()) + 86400
# Si aucune facture n'est passée en référence, on en crée une nouvelle.
if f is None:
f = Facture(self)
if isinstance(self, Adherent):
f.ajoute(cotisation.dico_adh)
elif isinstance(self, Club):
f.ajoute(cotisation.dico_adh_club)
f._set("finAdhesion", [generalizedTimeFormat(newFinAdh)])
f._set("debutAdhesion", [generalizedTimeFormat(thetime)])
self._set("finAdhesion", self._data.get("finAdhesion", []) + [generalizedTimeFormat(newFinAdh)])
self._set("debutAdhesion", self._data.get("debutAdhesion", []) + [generalizedTimeFormat(thetime)])
return f
def droits(self, droits=None, light=False): def droits(self, droits=None, light=False):
""" Renvoie les droits courants. Non modifiable (sauf si surchargée dans classe enfant)""" """ Renvoie les droits courants. Non modifiable (sauf si surchargée dans classe enfant)"""
if droits <> None: if droits <> None:
@ -1543,6 +1612,7 @@ class BaseProprietaire(BaseClasseCrans):
if not isadm() and isadm(self.compte()): if not isadm() and isadm(self.compte()):
raise EnvironmentError(u'Il faut être administrateur pour effectuer cette opération.') raise EnvironmentError(u'Il faut être administrateur pour effectuer cette opération.')
else: else:
if type(new) == list: if type(new) == list:
# Modif # Modif
@ -1651,18 +1721,30 @@ class BaseProprietaire(BaseClasseCrans):
else: else:
return [] return []
def factures(self): def factures(self, filtre=None):
""" Retourne les factures (instances) appartenant à la classe """ """ Retourne les factures (instances) appartenant à la classe """
# Le champ id n'est pas initialisé lorsque le proprio est en cours # Le champ id n'est pas initialisé lorsque le proprio est en cours
# de création # de création
if filtre is None:
filtre = Facture.filtre_idn
else:
filtre = "(&%s%s)" % (filtre, Facture.filtre_idn)
if self.id(): if self.id():
res = [] res = []
for r in self.conn.search_s('%s=%s,%s' % (self.idn, self.id(), self.base_dn), 1, Facture.filtre_idn): for r in self.conn.search_s('%s=%s,%s' % (self.idn, self.id(), self.base_dn), 1, filtre):
res.append(self.make(r, self._modifiable)) res.append(self.make(r, self._modifiable))
return res return res
else: else:
return [] return []
def factures_adh(self):
""" Retourne les factures pour adhésion """
return self.factures("(debutAdhesion=*)")
def factures_conn(self):
""" Retourne les factures pour connexion """
return self.factures("(debutConnexion=*)")
def solde(self, operation=None, comment=None): def solde(self, operation=None, comment=None):
""" Retourne ou modifie le solde d'un propriétaire """ Retourne ou modifie le solde d'un propriétaire
operation doit être un nombre positif ou négatif operation doit être un nombre positif ou négatif
@ -1825,8 +1907,12 @@ class BaseProprietaire(BaseClasseCrans):
return False return False
def paiement_ok(self): def paiement_ok(self):
if config.ann_scol in self.paiement() or (config.periode_transitoire and (config.ann_scol-1) in self.paiement()): if isinstance(self, Adherent):
if config.periode_transitoire or not isinstance(self, Adherent) or not config.bl_carte_et_definitif or config.ann_scol in self.carteEtudiant(): m_paiement = min(self.adhesion(), self.connexion())
else:
m_paiement = self.adhesion()
if config.ann_scol in self.paiement() or (config.periode_transitoire and (config.ann_scol-1) in self.paiement()) or (m_paiement > time.time()) or (config.periode_transitoire and config.debut_periode_transitoire <= m_paiement <= config.fin_periode_transitoire):
if config.periode_transitoire or not isinstance(self, Adherent) or not config.bl_carte_et_definitif or bool(self.carteEtudiant()):
return True return True
else: else:
return self.sursis_carte() return self.sursis_carte()
@ -2281,6 +2367,47 @@ class Adherent(BaseProprietaire):
# renvoie la valeur trouvée dans la base # renvoie la valeur trouvée dans la base
return bool(self._data.get('charteMA', [])) return bool(self._data.get('charteMA', []))
def connexion(self, mois=None, f=None):
"""
Gestion de la connexion d'un adhérent
* valeur est un entier définissant un nombre de mois
* f est une facture
"""
thetime = time.time()
# On récupère sur les factures l'ensemble de celles comportant une connexion.
conn_factures = self.factures_conn()
finConn = max([0.0] + [fromGeneralizedTimeFormat(facture._data.get('finConnexion', ["19700101000000Z"])[0]) for facture in conn_factures if facture.controle() != "FALSE"])
if mois is None:
return finConn
elif not isinstance(mois, int):
raise ValueError, u"Le nombre de mois doit être un entier"
else:
ftime = max(finConn, thetime)
# Calcul de la nouvelle date de fin d'adhésion.
curyear = datetime.datetime.now().year
curmonth = datetime.datetime.now().month
nbJours = 0
for i in xrange(1, mois+1):
nbJours += monthrange((curmonth + i - 1)/12 + curyear, (curmonth + i - 1)%12 + 12 * ((curmonth + i - 1) % 12 == 0))[1]
# On ajoute 3600 secondes sur suggestion de Raphaël Bonaque (<bonaque@crans.org>), pour tenir compte des malheureux qui
# pourraient subir le changement d'heure.
newFinConn = ftime + 86400 * nbJours + 3600
# Si aucune facture n'est passée en référence, on en crée une nouvelle.
if f is None:
f = Facture(self)
f.ajoute(cotisation.dico_cotis(mois))
f._set("finConnexion", [generalizedTimeFormat(newFinConn)])
f._set("debutConnexion", [generalizedTimeFormat(thetime)])
f._set("finConnexion", self._data.get("finConnexion", []) + [generalizedTimeFormat(newFinConn)])
f._set("debutConnexion", self._data.get("debutConnexion", []) + [generalizedTimeFormat(thetime)])
return f
def adherentPayant(self, valeur = None): def adherentPayant(self, valeur = None):
""" """
L'adhérent paie sa cotisation (a droit au WiFi, à un compte Crans, ... True par défaut L'adhérent paie sa cotisation (a droit au WiFi, à un compte Crans, ... True par défaut
@ -2354,7 +2481,11 @@ class Adherent(BaseProprietaire):
si positif ajoute l'année à la liste si positif ajoute l'année à la liste
si négatif le supprime si négatif le supprime
""" """
return self._an('carteEtudiant', action) if action == True:
self._set('carteEtudiant', ['TRUE'])
elif action == False:
self._set('carteEtudiant', [])
return bool(self._data.get('carteEtudiant', []))
def checkPassword(self, password): def checkPassword(self, password):
"""Vérifie le mot de passe de l'adhérent""" """Vérifie le mot de passe de l'adhérent"""
@ -3803,7 +3934,7 @@ class Facture(BaseClasseCrans):
self._set('modePaiement', [new]) self._set('modePaiement', [new])
return decode(self._data.get('modePaiement', [None])[0]) return decode(self._data.get('modePaiement', [''])[0])
def recuPaiement(self, new=None): def recuPaiement(self, new=None):
""" """
@ -3833,6 +3964,19 @@ class Facture(BaseClasseCrans):
# renvoie la valeur trouvée dans la base # renvoie la valeur trouvée dans la base
return self._data.get("recuPaiement", [None])[0] return self._data.get("recuPaiement", [None])[0]
def controle(self, action=None):
if action is None:
return self._data.get("controle", [''])[0]
else:
if action == True:
self._set("controle", ["TRUE"])
elif action == False:
self._set("controle", ["FALSE"])
elif action == "":
self._set("controle", [])
else:
raise ValueError("Mauvaise valeur pour l'attribut controle : %r" % (repr(action),))
def _del_recu_paiement(self): def _del_recu_paiement(self):
""" Pour test """ """ Pour test """
self._set("recuPaiement", []) self._set("recuPaiement", [])
@ -3940,7 +4084,7 @@ class Facture(BaseClasseCrans):
# enregistre la nouvelle liste # enregistre la nouvelle liste
self._articles(arts) self._articles(arts)
def supprime(self, supprime): def supprime(self, supprime=None, pop=None):
"""Supprime un/des article(s) à la facture """Supprime un/des article(s) à la facture
arts est un article ou une liste d'articles arts est un article ou une liste d'articles
""" """
@ -3951,6 +4095,9 @@ class Facture(BaseClasseCrans):
# charge la liste des articles # charge la liste des articles
arts = self._articles() arts = self._articles()
if pop is not None:
_ = arts.pop()
# on supprime les anciens articles # on supprime les anciens articles
if type(supprime)==dict: if type(supprime)==dict:
supprime = [supprime] supprime = [supprime]
@ -4062,6 +4209,10 @@ class _FakeProprio(CransLdap):
for r in res: for r in res:
m.append(self.make(r)) m.append(self.make(r))
return m return m
def adhesion(self):
return time.time() + 86400
def connexion(self):
return time.time() + 86400
class AssociationCrans(_FakeProprio): class AssociationCrans(_FakeProprio):
""" Classe définissant l'assoce (pour affichage de ses machines) """ """ Classe définissant l'assoce (pour affichage de ses machines) """

View file

@ -179,17 +179,13 @@ def adhers_brief(adhers) :
ook = u'\x1b[1;32mO\x1b[1;0m' ook = u'\x1b[1;32mO\x1b[1;0m'
nok = u'\x1b[1;31mn\x1b[1;0m' nok = u'\x1b[1;31mn\x1b[1;0m'
# Paiement # Paiement
if ann_scol in a.paiement(): if a.adhesion() > time() or a.paiement():
if 'p' in a.controle(): paid = ook if 'p' in a.controle(): paid = ook
else: paid = ok else: paid = ok
elif isinstance(a,Adherent) and not a.adherentPayant(): paid = coul('G', 'bleu')
else: paid = nok else: paid = nok
# Précablage
if ann_scol+1 in a.paiement() : paid = coul(paid,'f_vert')
# Carte d'étudiant # Carte d'étudiant
if ann_scol in a.carteEtudiant(): if a.carteEtudiant():
if 'c' in a.controle(): carte = ook if 'c' in a.controle(): carte = ook
else: carte = ok else: carte = ok
else : carte = nok else : carte = nok
@ -254,10 +250,7 @@ def machines_brief(machines) :
p = a.Nom() p = a.Nom()
# A jour administrativement # A jour administrativement
if ann_scol not in a.paiement() or ann_scol not in a.carteEtudiant(): if (a.adhesion() > time() and ann_scol not in a.paiement()) or not a.carteEtudiant():
if isinstance(a, Adherent) and not a.adherentPayant():
p = coul(p, 'bleu')
else:
p = coul(p,'rouge') p = coul(p,'rouge')
# Données # Données
@ -515,24 +508,22 @@ def adher_details(adher) :
f += u"\n" f += u"\n"
# État administratif # État administratif
f += coul("Date d'inscription : ", "gras") f += coul(u"Date d'inscription : ", "gras")
f += strftime('%d/%m/%Y %H:%M:%S', localtime(adher.dateInscription())) f += strftime('%d/%m/%Y %H:%M:%S', localtime(adher.dateInscription()))
f += coul(u'\nÉtat administratif : ','gras') f += coul(u'\nÉtat administratif : ','gras')
jour=1 jour = True
if ann_scol not in adher.carteEtudiant() : if not adher.carteEtudiant() :
f += coul(u"manque carte d'étudiant",'violet') f += coul(u"manque carte d'étudiant",'violet')
jour = 0 jour = False
if ann_scol not in adher.paiement() : if ann_scol not in adher.paiement() and (adher.adhesion() <= time()):
if not jour: f += ' et ' if not jour: f += ' et '
if isinstance(adher, Adherent) and not adher.adherentPayant():
f += coul(u"inscription gratuite ", 'bleu')
else: else:
f += coul(u"cotisation %s/%d non réglée"% (ann_scol, ann_scol+1 ),'violet') f += coul(u"Non adhérent actuellement.",'violet')
jour = 0 jour = False
if jour: if jour:
f += coul(u"à jour",'vert') f += coul(u"à jour",'vert')
f += '\n' f += "\n"
# Telephone # Telephone
tel = adher.tel() tel = adher.tel()
@ -591,30 +582,25 @@ def adher_details(adher) :
f += coul(u" (droits gelés car pas cotisé cette année)",'bleu') f += coul(u" (droits gelés car pas cotisé cette année)",'bleu')
f += u'\n' f += u'\n'
# Adhésion
if adher.adhesion() > time():
f += coul(u"Adhésion jusqu'au %s" % strftime("%d/%m/%Y %H:%M:%S", localtime(adher.adhesion())), "vert")
f += u"\n"
elif adher.paiement():
f += coul(u"Paiement pour %s/%s ok (connexion inclue)" % (ann_scol, ann_scol+1), "vert")
f += u"\n"
# Paiement # Paiement
if adher.paiement() : if adher.connexion() > time():
if len(adher.paiement()) == 1 : f += coul(u"Connexion jusqu'au %s" % strftime("%d/%m/%Y %H:%M:%S", localtime(adher.adhesion())), "vert")
f += coul(u'Cotisation payée pour l\'année scolaire :','gras') if adher.adhesion() < adher.connexion():
else : f += coul(u"(Théoriquement %s, sous réserve de réadhésion)" % (strftime("%d/%m/%Y %H:%M:%S", localtime(adher.connexion())),), "rouge")
f += coul(u'Cotisation payée pour les années scolaires :','gras')
g = u''
for an in adher.paiement() : g += u" %i-%i" % ( an, an+1 )
if len(g) > 35 : f += '\n\t'
f += g
if 'p' in adher.controle(): f += coul(u' (OK)', 'vert')
f += u'\n' f += u'\n'
# Cartes d'étudiant fournie # Carte d'étudiant fournie
if adher.carteEtudiant(): if adher.carteEtudiant():
if len(adher.carteEtudiant()) == 1 : f += coul(u"Carte d'étudiant fournie.",'gras')
f += coul(u"Carte d'étudiant fournie pour l'année scolaire :",'gras') if 'c' in adher.controle(): f += coul(u' (Contrôle OK)', 'vert')
else :
f += coul(u"Carte d'étudiant fournie pour les années scolaires :",'gras')
g = u''
for an in adher.carteEtudiant() : g += u" %i-%i" % ( an, an+1 )
if len(g) > 25 : f += '\n\t'
f += g
if 'c' in adher.controle(): f += coul(u' (OK)', 'vert')
f += u'\n' f += u'\n'
f += _blacklist(adher) f += _blacklist(adher)
@ -820,11 +806,10 @@ def club_details(club) :
# État administratif # État administratif
f += coul(u'État administratif : ','gras') f += coul(u'État administratif : ','gras')
jour=1 jour = True
if ann_scol not in club.paiement() : if club.adhesion() < time() and not club.paiement():
if not jour : f += ' et ' jour = False
f += coul(u"charte %s/%d non signée"% (ann_scol, ann_scol+1 ),'violet') f += coul(u"Non adhérent." ,'violet')
jour = 0
if jour: if jour:
f += coul(u"à jour",'vert') f += coul(u"à jour",'vert')
@ -843,14 +828,12 @@ def club_details(club) :
f += coul(u'VLAN : ','gras') + u'%s' % vlans f += coul(u'VLAN : ','gras') + u'%s' % vlans
f += u'\n' f += u'\n'
# Paiement # Adhésion
if club.paiement() : if club.adhesion() > time():
f += coul(u'Charte signée pour les années scolaires :','gras') f += coul(u"Adhésion jusque %s." % (strftime("%d/%m/%Y %H:%M:%S", localtime(club.adhesion())),), "vert")
g = '' f += '\n'
for an in club.paiement() : g += " %i-%i" % ( an, an+1 ) elif ann_scol in club.paiement():
if len(g) > 35 : f += '\n\t' f += coul(u"Adhésion pour l'année en cours", "vert")
f += g
if 'p' in club.controle(): f += coul(u' (OK)', 'vert')
f += '\n' f += '\n'
login = club.compte() login = club.compte()
@ -883,6 +866,14 @@ def club_details(club) :
else : else :
f += 'aucune' f += 'aucune'
f += u"\n"
f += coul(u'Facture(s) : ','gras')
m = club.factures()
if m :
f += u'\n' + list_factures(m)
else :
f += u'aucune'
return f return f
########################################### ###########################################
@ -1014,8 +1005,6 @@ def borne_clients_canal(borne) :
wl = subprocess.Popen("ssh -o StrictHostKeyChecking=no -i %s root@%s 'cat /tmp/auth-mac.dump ; echo -n \"CANAL \" ; /usr/sbin/nvram get wl0_channel'" % (clef, borne), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True) wl = subprocess.Popen("ssh -o StrictHostKeyChecking=no -i %s root@%s 'cat /tmp/auth-mac.dump ; echo -n \"CANAL \" ; /usr/sbin/nvram get wl0_channel'" % (clef, borne), shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
wl.stdin.close() wl.stdin.close()
for line in wl.stdout.readlines(): for line in wl.stdout.readlines():
print 'coucou'
print line
# Chaque ligne est de la forme # Chaque ligne est de la forme
# 00:11:22:33:44:55 -20 # 00:11:22:33:44:55 -20
line = line.strip().split() line = line.strip().split()

View file

@ -49,13 +49,17 @@ elif arg == "fichier" :
data = db.search(filtre) data = db.search(filtre)
return len(data['adherent']) + len(data['club']) return len(data['adherent']) + len(data['club'])
def count_adh():
data = db.get_adherents()
return len(data['adherent']) + len(data['club'])
total = 0 total = 0
for bat in 'abcghijmpo' : for bat in 'abcghijmpo' :
nb = count('paiement=ok&chbre=%s*' % bat) nb = count_adh()
total += nb total += nb
file.write("bat%s.value %d\n" % (bat, nb)) file.write("bat%s.value %d\n" % (bat, nb))
nb = count('paiement=ok&chbre=EXT') nb = count_adh()
total += nb total += nb
file.write("wifi.value %d\n" % nb) file.write("wifi.value %d\n" % nb)

View file

@ -16,7 +16,11 @@ ACTIONS POSSIBLES
# Licence : GPLv2 # Licence : GPLv2
import sys, os, re, time, cPickle import sys
import os
import re
import time
import cPickle
from time import mktime, time, localtime, strptime, strftime from time import mktime, time, localtime, strptime, strftime
from socket import gethostname from socket import gethostname
from smtplib import SMTP from smtplib import SMTP
@ -208,7 +212,7 @@ comptes_inactifs.py
mail = nb_mails_non_lus(login) mail = nb_mails_non_lus(login)
mail = mail == None and u'?' or mail > 0 and u'X' or u' ' mail = mail == None and u'?' or mail > 0 and u'X' or u' '
ligne = (a.id(), login, a.Nom(), date, forward, mail) ligne = (a.id(), login, a.Nom(), date, forward, mail)
if ann_scol in a.paiement(): if ann_scol in a.paiement() or a.adhesion() > time():
inscrits.append(ligne) inscrits.append(ligne)
else: else:
anciens.append(ligne) anciens.append(ligne)

View file

@ -26,14 +26,10 @@ def chap_ok(password, challenge, clear_pass) :
return False return False
def paiement_ok(adh): def paiement_ok(adh):
"""Paiment ok ?""" """Vérifie que le paiement est ok
global ann_scol
paid = max(adh.paiement() + [0]) """
if periode_transitoire: return adh.paiement_ok()
# Si periode transitoire, on accepte les personnes n'ayant pas
# réadhéré
ann_scol -= 1
return ann_scol <= paid
def do_auth(mac, prise): def do_auth(mac, prise):
"""Effectue l'authentification. Renvoie (success, msg, """Effectue l'authentification. Renvoie (success, msg,