Commit 7f1ffbee authored by Pierre-Elliott Bécue's avatar Pierre-Elliott Bécue

Passage aux adhésions glissantes (partie 2/2, lc_ldap)

parent 68800519
......@@ -48,6 +48,7 @@ import random
import string
from unicodedata import normalize
from crans_utils import format_tel, format_mac, mailexist, validate_name, ip4_of_rid, ip6_of_mac, fetch_cert_info
from crans_utils import toGeneralizedTimeFormat, fromGeneralizedTimeFormat, extractTz
import itertools
sys.path.append("/usr/scripts")
......@@ -557,12 +558,86 @@ class derniereConnexion(intAttr):
can_modify = [nounou, cableur, soi] # il faut bien pouvoir le modifier pour le mettre à jour
ldap_name = "derniereConnexion"
class generalizedTimeFormat(Attr):
"""Classe définissant un ensemble de données pour manipuler
une donnée de temps suivant la RFC 4517
"""
default = "19700101000000Z"
def __float__(self):
return self._stamp
def __int__(self):
return int(self._stamp)
def __eq__(self, othertime):
if isinstance(self, othertime):
return self._stamp == othertime._stamp
else:
resource = generalizedTimeFormat(othertime, conn=None, Parent=None)
return self._stamp == resource._stamp
def __neq__(self, othertime):
return not (self == othertime)
def __lt__(self, othertime):
if isinstance(othertime, generalizedTimeFormat):
return self._stamp < othertime._stamp
else:
resource = generalizedTimeFormat(othertime, conn=None, Parent=None)
return self._stamp < resource._stamp
def __gt__(self, othertime):
return not (self < othertime) and not (self == othertime)
def parse_value(self, gtf):
if isinstance(gtf, str) or isinstance(gtf, unicode):
if not ('Z' in gtf or '+' in gtf or '-' in gtf):
self._stamp = gtf
self.value = toGeneralizedTimeFormat(float(gtf))
else:
self._stamp = fromGeneralizedTimeFormat(gtf)
self.value = gtf
elif isinstance(gtf, float):
self._stamp = gtf
self.value = toGeneralizedTimeFormat(gtf)
@crans_attribute
class debutAdhesion(generalizedTimeFormat):
legend = u"Date de début de l'adhésion"
category = 'Adh'
can_modify = [cableur, nounou]
ldap_name = 'debutAdhesion'
@crans_attribute
class finAdhesion(generalizedTimeFormat):
legend = u"Date de fin de l'adhésion"
category = 'Adh'
can_modify = [cableur, nounou]
ldap_name = 'finAdhesion'
@crans_attribute
class debutConnexion(generalizedTimeFormat):
legend = u"Date de début de la connexion"
category = 'Adh'
can_modify = [cableur, nounou]
ldap_name = 'debutConnexion'
@crans_attribute
class finConnexion(generalizedTimeFormat):
legend = u"Date de fin de la connexion"
category = 'Adh'
can_modify = [cableur, nounou]
ldap_name = 'finConnexion'
@crans_attribute
class mail(Attr):
singlevalue = False
optional = False
unique = True
legend = "Adresse mail de l'adhérent"
legend = u"Adresse mail de l'adhérent"
can_modify = [soi, nounou, cableur]
category = 'mail'
ldap_name = "mail"
......@@ -1446,7 +1521,7 @@ class controle(Attr):
ldap_name = "controle"
def parse_value(self, ctrl):
if ctrl not in [u"", u"c", u"p", u"cp", u"pc"]:
if ctrl not in [u"", u"c", u"p", u"cp", u"pc", u"TRUE", u"FALSE"]:
raise ValueError("Contrôle peut prendre les valeurs [c][p]")
self.value = ctrl
......
......@@ -306,3 +306,29 @@ def ip4_addresses():
ip_list.append(link['addr'])
return ip_list
def extractTz(thetz):
abstz = 100*abs(thetz)
if thetz == 0:
return "Z"
else:
return "%s%04d" % ("+"*(thetz < 0) + "-"*(thetz > 0), abstz)
def toGeneralizedTimeFormat(stamp):
"""Converts a timestamp (local) in a generalized time format
for LDAP.
* stamp : float value
* output : a string without the dot second
"""
return "%s%s" % (time.strftime("%Y%m%d%H%M%S", time.localtime(stamp)), extractTz(time.altzone/3600))
def fromGeneralizedTimeFormat(gtf):
"""Converts a GTF stamp to unix timestamp
* gtf : a generalized time format resource without dotsecond
* output : a float value
"""
return time.mktime(time.strptime(gtf.split("-", 1)[0].split("+", 1)[0].split('Z', 1)[0], "%Y%m%d%H%M%S"))
......@@ -713,10 +713,13 @@ class proprio(CransLdapObject):
u""" Un propriétaire de machine (adhérent, club…) """
can_be_by = { variables.created: [attributs.nounou, attributs.bureau, attributs.cableur],
variables.modified: [attributs.nounou, attributs.bureau, attributs.soi, attributs.cableur],
variables.deleted: [attributs.nounou, attributs.bureau],
variables.deleted: [attributs.nounou, attributs.bureau,],
}
attribs = [attributs.nom, attributs.chbre, attributs.paiement, attributs.info, attributs.blacklist, attributs.controle, attributs.historique]
attribs = [attributs.nom, attributs.chbre, attributs.paiement, attributs.info,
attributs.blacklist, attributs.controle, attributs.historique,
attributs.debutAdhesion, attributs.finAdhesion, attributs.debutConnexion,
attributs.finConnexion]
def __repr__(self):
return str(self.__class__) + " : nom=" + str(self['nom'][0])
......@@ -857,6 +860,14 @@ class proprio(CransLdapObject):
u"""Renvoie si le propriétaire a payé et donné sa carte pour l'année en cours"""
return self.paiement_ok() and self.carte_ok()
def fin_adhesion(self):
"""Retourne la date de fin d'adhésion"""
return max([float(facture.get('finAdhesion', [crans_utils.fromGeneralizedTimeFormat(attributs.finAdhesion.default)])[0]) for facture in self.factures() if facture.get('controle', [''])[0] != u"FALSE"] + [0.0])
def fin_connexion(self):
"""Retourne la date de fin de connexion"""
return max([float(facture.get('finConnexion', [crans_utils.fromGeneralizedTimeFormat(attributs.finConnexion.default)])[0]) for facture in self.factures() if facture.get('controle', [''])[0] != u"FALSE"] + [0.0])
def paiement_ok(self, no_bl=False):
u"""
Renvoie si le propriétaire a payé pour l'année en cours, en prenant en compte les périodes de transition et les blacklistes.
......@@ -868,7 +879,13 @@ class proprio(CransLdapObject):
for bl in self.blacklist_actif():
if bl['type'] == 'paiement':
return False
return config.ann_scol in self['paiement'] or (config.periode_transitoire and (config.ann_scol - 1) in self['paiement'])
old_style_paiement = config.ann_scol in self['paiement'] or (config.periode_transitoire and (config.ann_scol - 1) in self['paiement'])
if isinstance(self, adherent):
fin_paiement = min(self.fin_adhesion(), self.fin_connexion())
else:
fin_paiement = self.fin_adhesion()
new_style_paiement = time.time() < fin_paiement or (config.periode_transitoire and config.debut_periode_transitoire <= fin_paiement <= config.fin_periode_transitoire)
return (old_style_paiement or new_style_paiement)
def carte_ok(self):
u"""Renvoie si le propriétaire a donné sa carte pour l'année en cours, en prenant en compte les periode transitoires et le sursis carte"""
......@@ -1251,7 +1268,9 @@ class facture(CransLdapObject):
variables.deleted: [attributs.nounou, attributs.bureau, attributs.cableur],
}
attribs = [attributs.fid, attributs.modePaiement, attributs.recuPaiement,
attributs.historique, attributs.article, attributs.info]
attributs.historique, attributs.article, attributs.info,
attributs.debutAdhesion, attributs.finAdhesion, attributs.debutConnexion,
attributs.finConnexion, attributs.controle ]
ldap_name = "facture"
_proprio = None
......
#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
from gestion.affich_tools import coul, tableau
from gestion.affichage import style, tableau
import importlib
import time
import ldap
import sys
import gestion.config as config
# Import inutile, mais on en a besoin pour que le
# script continue à fonctionner.
......@@ -35,9 +36,9 @@ def prise_etat(chbre):
# fonction prise_etat propre à lc_ldap, pour
# ne plus en avoir besoin ci-après.
gestion.whos = try_import(u"gestion.whos")
gestion.whos.coul = coul
gestion.whos.style = style
if chbre=="????":
return coul("Chambre invalide", "violet")
return style("Chambre invalide", "violet")
return gestion.whos.prise_etat(chbre)[0]
def timeformat(t, format):
......@@ -50,13 +51,13 @@ def blacklists(l):
fin=b['fin'] if b['fin'] == '-' else time.strftime("%d/%m/%Y %H:%M", time.localtime(b['fin']))
couleur='rouge' if b['actif'] else None
if debut != '-' and fin !='-':
bl.append(coul(u"du %s au %s : %s [%s]" % (debut, fin, b['type'], b['comm']), couleur))
bl.append(style(u"du %s au %s : %s [%s]" % (debut, fin, b['type'], b['comm']), couleur))
elif debut != '-':
bl.append(coul(u"À partir du %s : %s [%s]" % (debut, b['type'], b['comm']), couleur))
bl.append(style(u"À partir du %s : %s [%s]" % (debut, b['type'], b['comm']), couleur))
elif fin != '-':
bl.append(coul(u"Jusqu'au %s : %s [%s]" % (fin, b['type'], b['comm']), couleur))
bl.append(style(u"Jusqu'au %s : %s [%s]" % (fin, b['type'], b['comm']), couleur))
else:
bl.append(coul(u"%s [%s]" % (b['type'], b['comm']), couleur))
bl.append(style(u"%s [%s]" % (b['type'], b['comm']), couleur))
return bl
def split(str, *arg):
......@@ -90,19 +91,19 @@ def const_of_mac(mac):
templateEnv=None
def template(dialog=False):
global templateEnv, coul, tableau
global templateEnv, style, tableau
if not templateEnv:
# un import paresseux, comme ça, pas la peine d'installer jinja2 sur les machines où il n'y en a pas besoin
import jinja2
oldcoul = coul
oldstyle = style
oldtableau = tableau
tableau = lambda *args,**kwargs: oldtableau(*args,dialog=dialog,**kwargs)
coul = lambda *args,**kwargs:oldcoul(*args,dialog=dialog,**kwargs)
style = lambda *args,**kwargs:oldstyle(*args,dialog=dialog,**kwargs)
template_path = '/usr/scripts/lc_ldap/printing/templates/'
templateLoader = jinja2.FileSystemLoader( searchpath=["/", template_path] )
templateEnv = jinja2.Environment( loader=templateLoader, trim_blocks=True )
templateEnv.add_extension('jinja2.ext.do')
templateEnv.filters['coul'] = coul
templateEnv.filters['coul'] = style
templateEnv.filters['blacklists'] = blacklists
templateEnv.filters['prise_etat'] = prise_etat
templateEnv.filters['timeformat'] = timeformat
......@@ -130,7 +131,7 @@ def list_machines(machines, width=None):
def list_factures(factures, width=None):
return tableau([
[f['fid'][0], f['modePaiement'][0],
coul("OK", "vert") if f.get('recuPaiement', []) else coul("NON", "rouge"),
style("OK", "vert") if f.get('recuPaiement', []) else style("NON", "rouge"),
' '.join(attr['code'] for attr in f.get('article',[])),
u"%s€" % sum([float(a['pu'])*int(a['nombre']) for a in f.get('article',[])])
] for f in factures],
......@@ -143,8 +144,8 @@ def list_adherents(adherents, width=None):
return tableau([
[a['aid'][0],
u' '.join(unicode(i) for i in a['prenom'] + a['nom']),
a['chbre'][0], coul('o', 'vert') if a.paiement_ok() else coul('n', 'rouge'),
coul('o', 'vert') if a.carte_ok() else coul('n', 'rouge'),
a['chbre'][0], style('o', 'vert') if a.paiement_ok() else style('n', 'rouge'),
style('o', 'vert') if a.carte_ok() else style('n', 'rouge'),
u', '.join(unicode(m['host'][0]).split('.',1)[0] for m in a.machines())
] for a in adherents ],
titre = [u'aid', u'Prénom Nom', u'Chbre', u'P', u'C', u'Machines'],
......@@ -156,7 +157,7 @@ def list_clubs(clubs, width=None):
return tableau([
[a['cid'][0],
u' '.join(unicode(i) for i in a['nom']),
a['chbre'][0], coul('o', 'vert') if a.paiement_ok() else coul('n', 'rouge'),
a['chbre'][0], style('o', 'vert') if a.paiement_ok() else style('n', 'rouge'),
u', '.join(unicode(m['host'][0]).split('.',1)[0] for m in a.machines())
] for a in clubs ],
titre = [u'cid', u'Nom', u'Chbre', u'P', u'Machines'],
......@@ -168,14 +169,39 @@ def proprio(proprio, params):
params['o']=proprio
etat_administratif=[]
if proprio.paiement_ok() and proprio.carte_ok():
etat_administratif.append(coul(u"à jour", "vert"))
etat_administratif.append(style(u"à jour", "vert"))
if not proprio.carte_ok():
etat_administratif.append(coul(u"manque carte d'étudiant", "violet"))
etat_administratif.append(style(u"manque carte d'étudiant", "violet"))
if not proprio.paiement_ok():
etat_administratif.append(coul(u"cotisation non réglée", "violet"))
etat_administratif.append(style(u"cotisation non réglée", "violet"))
if proprio.fin_adhesion() >= time.time():
adh = style(u"Adhésion jusqu'au %s" % (time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(proprio.fin_adhesion())),), "vert")
elif config.ann_scol in proprio['paiement']:
adh = style(u"Adhésion pour la période %s-%s ok." % (config.ann_scol, config.ann_scol+1), "vert")
elif proprio.paiement_ok():
adh = style(u"Adhésion terminée, mais il y a un sursis.", 'orange')
else:
adh = style(u"Pas adhérent actuellement.", 'rouge')
params["adh"] = adh
if proprio.fin_connexion() >= time.time():
conn = style(u"Connexion jusqu'au %s" % (time.strftime("%d/%m/%Y %H:%M:%S", time.localtime(proprio.fin_connexion())),), "vert")
elif config.ann_scol in proprio['paiement']:
conn = style(u"Connexion pour la période %s-%s ok." % (config.ann_scol, config.ann_scol+1), "vert")
elif proprio.paiement_ok():
conn = style(u"Connexion terminée, mais il y a un sursis.", 'orange')
else:
conn = style(u"Pas connecté actuellement.", 'rouge')
params["conn"] = conn
if proprio.get('carteEtudiant', []):
cetud = style(u"Carte d'étudiant fournie.", 'vert')
elif proprio.sursis_carte() or proprio.carte_ok():
cetud = style(u"Carte d'étudiant non fournie, mais en sursis.", 'orange')
else:
cetud = style(u"Pas de carte d'étudiant")
params["cetud"] = cetud
params['etat_administratif']=etat_administratif
if proprio["chbre"][0].value not in ["????", "EXT"]:
params['brassage'] = coul("Cr@ns", "bleu") if gestion.annuaires_pg.is_crans(proprio["chbre"][0].value[0], proprio["chbre"][0].value[1:]) else coul("CROUS", "jaune")
params['brassage'] = style("Cr@ns", "bleu") if gestion.annuaires_pg.is_crans(proprio["chbre"][0].value[0], proprio["chbre"][0].value[1:]) else style("CROUS", "jaune")
try:
if proprio.machines():
......
......@@ -11,6 +11,10 @@
{{"Chambre : "|coul('gras')}}{{o.chbre.0}} ({{o.chbre.0|string|prise_etat}})
{% endif %}
{{"Études : "|coul('gras')}}{{o.etudes|join(' ')}}
{{"Cotisation payée pour les années : "|coul('gras')}}{{o.paiement|join(' ')}} {% if o.get('controle', []) and 'p' in o.controle.0.value %}{{"(OK)"|coul('vert')}}{% endif %}
{{"Carte d'étudiant fournie pour les années : "|coul('gras')}}{{o.carteEtudiant|join(' ')}} {% if o.get('controle', []) and 'c' in o.controle.0.value %}{{"(OK)"|coul('vert')}}{% endif %}
{{adh}} {% if o.get('controle', []) and 'p' in o.controle.0.value %}{{"(OK)"|coul('vert')}}{% endif %}
{{conn}} {% if o.get('controle', []) and 'p' in o.controle.0.value %}{{"(OK)"|coul('vert')}}{% endif %}
{{cetud}} {% if o.get('controle', []) and 'c' in o.controle.0.value %}{{"(OK)"|coul('vert')}}{% endif %}
{% endblock%}
......@@ -7,5 +7,5 @@
{{"Imprimeurs : "|coul('gras')}}{% for i in o.imprimeurClub %}{{i.value.prenom|join(' ')}} {{i.value.nom|join(' ')}} ({{i.value.aid|join(' ')}}) {% endfor%}
{{"Local : "|coul('gras')}}{{o.chbre.0}} ({{o.chbre.0|string|prise_etat}})
{{"Charte signée pour les années scolaires : "|coul('gras')}}{{o.paiement|join(' ')}}
{{adh}}
{% endblock%}
......@@ -16,7 +16,7 @@ import gestion.config as config
# liste des attributs dont dépend un service
services_to_attrs = {}
services_to_attrs['macip'] = [ attributs.ipHostNumber, attributs.ip6HostNumber, attributs.macAddress, attributs.paiement, attributs.carteEtudiant ]
services_to_attrs['macip'] = [ attributs.ipHostNumber, attributs.ip6HostNumber, attributs.macAddress, attributs.paiement, attributs.carteEtudiant, attributs.finConnexion ]
services_to_attrs['dns'] = [ attributs.ipHostNumber, attributs.ip6HostNumber, attributs.sshFingerprint, attributs.host, attributs.hostAlias, attributs.dnsIpv6 , attributs.hostCert, attributs.portTCPin, attributs.portUDPin ]
services_to_attrs['blacklist'] = [ attributs.blacklist, attributs.chbre, attributs.mailInvalide ] + services_to_attrs['macip']
services_to_attrs['ports'] = [ attributs.portUDPout, attributs.portUDPin, attributs.portTCPout, attributs.portTCPin ]
......@@ -319,7 +319,7 @@ def services_to_restart(conn, old_attrs={}, new_attrs={}, created_object=[], del
if 'cransAccount' in added_objectClass:
arg = services_to_args['home'](added_objectClass[0])
service_to_restart(conn, "home", list(arg), 0)
if 'cransAccount' in deleted_objectClass:
service_to_restart(conn, "del_user", ["%s,%s" % (old_attrs['uid'][0], old_attrs['homeDirectory'][0])], 0)
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment