scripts/impression/recredit.py
2015-07-19 14:59:25 +02:00

165 lines
5.4 KiB
Python
Executable file
Raw Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/bin/bash /usr/scripts/python.sh
# -*- coding: utf-8 -*-
"""
Effectue la recréditation des impressions qui n'ont pas été effectuées
par l'imprimante, soit ne sont pas sorties correctement, et contiennent
des logs d'erreur.
Le script est fait pour éviter de recréditer plusieurs fois les mêmes
impressions, et croise dans l'historique de l'adhérent les impressions
(débits), et les créditations que ce script a lui même déjà effectuées.
Un mail est envoyé pour signaler les activités de crédits.
L'exécution se fait pas appel du script suivi de l'aid.
Auteurs : Gabriel Détraz <detraz@crans.org>
Pierre-Elliott Bécue <becue@crans.org>
avec contributions importantes de Daniel Stan, Valentin Samir et Lucas Serrano
"""
# Import des modules génériques
import argparse
import sys
import datetime
import re
from utils.sendmail import actually_sendmail
# Imports des scripts développés au Crans
import lc_ldap.shortcuts
import lc_ldap.filter2 as lfilter
import gestion.config as config
from pythondialog.dialog import Dialog
from gestion import mail
# On ouvre une connexion LDAP à la base de test une fois pour toute.
conn = lc_ldap.shortcuts.lc_ldap_admin()
# Des fonctions...
IMP_DONE_REGEX = re.compile(r".*debit (?P<montant>[^ ]*) Euros \[impression\((?P<jid>.*)\):.*/(?P<login>.*)/(?P<file>[^ ]*) .*\]")
IMP_DEJ_REMB_REGEX = re.compile(r".*credit (?P<montant>[^ ]*) Euros \[Impression ratee, jid=(?P<jid>.*), tache=(?P<fichier>.*)\]")
def do_remb(args):
"""Fonction appelant l'interface curses et listant les remboursements
possibles.
"""
rendu = []
adh = conn.search(lfilter.human_to_ldap(args.filtre.decode(config.encoding.in_encoding)), mode="w")
# conn.search peut retourner une liste vide.
if not adh:
return []
with adh[0] as adh:
liste_rembs = find_rembs(adh)
while True:
(ret, val) = dialog_remb(liste_rembs)
if ret:
adh.save()
break
else:
selected = liste_rembs[int(val)]
if confirm(selected):
adh.update_solde(float(selected["montant"]), u"Impression ratee, jid=%(jid)s, tache=%(file)s" % selected)
_ = liste_rembs.pop(int(val))
rendu.append(selected)
else:
continue
send_mail(rendu, adh)
return
def find_rembs(adh):
"""Fonction qui calcule les entrées remboursables d'un adhérent
"""
now = datetime.datetime.now()
begin = now - datetime.timedelta(days=config.impression.delta_recredit_jours)
liste_taches = list()
liste_rembs = list()
for ent in adh["historique"]:
date = ent.get_datetime()
if date > begin:
match_entry = IMP_DONE_REGEX.match(unicode(ent))
if match_entry is not None:
liste_taches.append(match_entry.groupdict())
continue
match_entry = IMP_DEJ_REMB_REGEX.match(unicode(ent))
if match_entry is not None:
liste_rembs.append(match_entry.groupdict())
continue
# On génère la liste avant le return, pour ne pas la regénérer autant de fois qu'il
# y a de tâches dans liste_taches
jid_rembs = [remb["jid"] for remb in liste_rembs]
return [tache for tache in liste_taches if tache['jid'] not in jid_rembs]
def dialog_remb(liste_rembs):
"""Crée une boîte de dialogue à partir de la liste des remboursements, pour
en faire un.
"""
if not liste_rembs:
return (1, "")
dialog = Dialog()
choices = [("%s" % liste_rembs.index(dico), "Remb impression du fichier %(file)s (montant: %(montant)s, jid: %(jid)s)." % dico) for dico in liste_rembs]
return dialog.menu("Quelle impression souhaitez-vous rembourser ?", width=0, height=0, menu_height=0, title="Remboursement", choices=choices, cancel_label="Quitter", backtitle=u"Remboursement d'impressions ratées.")
def confirm(dico):
"""Demande avec dialog si on doit confirmer le remboursement.
"""
dialog = Dialog()
return dialog.yesno("Confirmer le remboursement ?") == dialog.DIALOG_OK
def send_mail(liste_rendus, adh):
"""Si la liste des remboursements est non-vide, envoie un mail pour prévenir
les imprimeurs.
"""
if not liste_rendus:
return
montant = sum([float(dico["montant"]) for dico in liste_rendus])
affs = [dico['file'] for dico in liste_rendus]
login = unicode(adh["uid"][0])
# print adh.get_mail()
To = adh.get_mail()
From = 'impression@crans.org'
Cc = 'impression@crans.org'
mailtxt = mail.generate('remboursement_impressions', {
'To': To,
'From': From,
'adhname': login,
'taches': u', '.join(affs),
'montant': montant,
'imprimeur': lc_ldap.shortcuts.current_user,
})
# print mailtxt.as_string()
actually_sendmail(From, (To, Cc), mailtxt)
#Un bloc de test
if __name__ == "__main__":
parser = argparse.ArgumentParser(description="Script pour recréditer les adhérents.", add_help=False)
parser.add_argument('-h', '--help', help="Affiche ce message et quitte.", action="store_true")
parser.add_argument('filtre', type=str, nargs="?", help="Le filtre LDAP à utiliser")
# Et on parse
args = parser.parse_args()
if args.help:
parser.print_help()
sys.exit(0)
else:
if not args.filtre:
parser.print_help()
sys.exit(1)
else:
do_remb(args)