diff --git a/controle_adhesion/main.py b/controle_adhesion/main.py index a76ce74..2ffa77c 100755 --- a/controle_adhesion/main.py +++ b/controle_adhesion/main.py @@ -257,7 +257,7 @@ def validate_registrations_worker(): BUF.append("=> MEMBRE VALIDE PAR SECRETARIAT <=") # Launch git tickets - request = { 'title' : "Création d'un compte courriel membre n°{}".format(numero), + request = { 'title' : "Création d'un compte courriel membre n°{}.".format(numero), 'labels' : "Nouveau membre", 'confidential' : "yes", 'description' : "Bonjour,\n Une demande de création de compte de" \ diff --git a/controle_cotisation/main.py b/controle_cotisation/main.py index 611e839..e2c3c4a 100644 --- a/controle_cotisation/main.py +++ b/controle_cotisation/main.py @@ -22,9 +22,9 @@ from requests.auth import HTTPDigestAuth VERSION="0.0.1" -GESTION_SECRET_FILE="/home/tresorier/.secret/gestion_api_password" -GIT_SECRET_FILE="/home/tresorier/.secret/git_api_password" -WORKDIR="/srv/validation_cotisation.d" +GESTION_SECRET_FILE=".secret/gestion_api_password" +GIT_SECRET_FILE=".secret/git_api_password" +WORKDIR=".validation_cotisation.d" MODALITY_MAIL="mail_instructions.txt" MODALITY_MAIL_HEADERS="mail_instructions_headers.txt" RECEPT_MAIL="mail_recu.txt" @@ -67,10 +67,10 @@ def gestion_read(req): data = req) return response.json() -def git_mail_ticket_create(req): - response = requests.post('https://git.a-lec.org/api/v4/projects/46/issues', +def git_mail_ticket_read(req): + response = requests.get('https://git.a-lec.org/api/v4/projects/46/issues', headers={'PRIVATE-TOKEN' : git_get_secret()}, - data = req) + params = req) return response.json() def git_xmpp_ticket_create(req): @@ -94,6 +94,8 @@ def setup_workdir(): os.mkdir(WORKDIR+"/expiré") if not "validé" in os.listdir(WORKDIR): os.mkdir(WORKDIR+"/validé") + if not "transition" in os.listdir(WORKDIR): + os.mkdir(WORKDIR+"/transition") def sendmail(headers, data): msg = bytes(headers + "\n", 'utf-8') + quopri.encodestring(bytes(data, 'utf-8')) @@ -102,13 +104,237 @@ def sendmail(headers, data): def sendmail_with_attachment(headers, data, attachment_header, attachment): msg = bytes(headers + "\n", 'utf-8') \ + quopri.encodestring(bytes(data, 'utf-8')) \ - + bytes(attachment_header + "\n", 'utf-8') + + bytes(attachment_header + "\n", 'utf-8') \ + bytes(attachment, 'base64') subprocess.run([SENDMAIL_LOCATION, "-t", "-oi"], input=msg) +def gestion_get_expired(): + request_expired = "SELECT id_user FROM services_users su " +\ + "INNER JOIN membres m ON m.id = su.id_user " +\ + "INNER JOIN services s ON s.id = su.id_service " +\ + "LEFT JOIN services_fees sf ON sf.id = su.id_fee " +\ + "INNER JOIN (SELECT id, MAX(date) " +\ + "FROM services_users " +\ + "GROUP BY id_user, id_service) " +\ + "AS su2 ON su2.id = su.id " +\ + "WHERE su.id_service = 1 " +\ + "AND su.expiry_date < date() " +\ + "AND NOT (m.id_category = 10 " +\ + "OR m.id_category = 3 " +\ + "OR m.id_category = 2 " +\ + "OR m.id_category = 8);" + expired_members_list = \ + [ str(x["id_user"]) for x in gestion_read(request_expired)["results"]] + + return expired_members_list.copy() + +def gestion_get_unpaid(): + request_unpaid = "SELECT id_user FROM services_users su " +\ + "INNER JOIN membres m ON m.id = su.id_user " +\ + "INNER JOIN services s ON s.id = su.id_service " +\ + "LEFT JOIN services_fees sf ON sf.id = su.id_fee " +\ + "INNER JOIN (SELECT id, MAX(date) " +\ + "FROM services_users " +\ + "GROUP BY id_user, id_service) " +\ + "AS su2 ON su2.id = su.id " +\ + "WHERE su.id_service = 1 " +\ + "AND su.paid = 0 " +\ + "AND NOT (m.id_category = 10 " +\ + "OR m.id_category = 3 " +\ + "OR m.id_category = 2 " +\ + "OR m.id_category = 8);" + + + unpaid_members_list = \ + [ str(x["id_user"]) for x in gestion_read(request_unpaid)["results"]] + + return unpaid_members_list.copy() + +def get_member_infos(member): + request = "SELECT * FROM membres " +\ + "WHERE id = '{}';".format(member) + try: + name = gestion_read(request)['results'][-1]['nom'] + numero = gestion_read(request)['results'][-1]['numero'] + email = gestion_read(request)['results'][-1]['email'] + except: + print(gestion_read(request)) + raise(Exception) + return (name, numero, email) + +def check_email_created(member): + + # Get member infos + name, numero, email = get_member_infos(member) + + request = { 'not[labels]' : "Résolu", + 'state' : "opened" } + answer = git_mail_ticket_read(request) + + for ticket in answer: + if "n°{}.".format(numero) in ticket['title']: + return False + return True + +def notify_expired(member): + BUF.append("* {}".format(member)) + BUF.append(" NOTIFICATION TRESORIER") + BUF.append("") + +def notify_unpaid(member): + if not check_email_created(member): + return False + + # Get member infos + name, numero, email = get_member_infos(member) + + BUF.append("* {} (numero {}), {}".format(member, numero, name)) + BUF.append(" NOTIFICATION MEMBRE") + BUF.append("") + return True + +def renotify_unpaid(member): + + # Get member infos + name, numero, email = get_member_infos(member) + + BUF.append("* {} (numero {}), {}".format(member, numero, name)) + BUF.append(" RENOTIFICATION MEMBRE") + BUF.append("") + pass + +def check_expired_unpaid(): + expired_members = gestion_get_expired() + unpaid_members = gestion_get_unpaid() + + # Check expired members + if set(expired_members) != set(os.listdir(WORKDIR+"/expiré")): + BUF.append("Membres expirés : {}".format(gestion_get_expired())) + + # Check for no-more-expired members + for record in os.listdir(WORKDIR+"/expiré"): + if not record in expired_members: + os.rename(WORKDIR+"/expiré/"+record, + WORKDIR+"/transition/"+record) + + # Check for new expired members + for member in expired_members: + if not str(member) in os.listdir(WORKDIR+"/expiré"): + set_file_content(WORKDIR+"/expiré/"+str(member), "") + notify_expired(member) + + # Check unpaid members + if set(unpaid_members) != set(os.listdir(WORKDIR+"/impayé")): + BUF.append("Membres en impayé : {}".format(gestion_get_unpaid())) + + # Check for no-more-unpaid members + for record in os.listdir(WORKDIR+"/impayé"): + if not record in unpaid_members: + os.rename(WORKDIR+"/impayé/"+record, + WORKDIR+"/transition/"+record) + + # Check for new unpaid members and set date of first contact + for member in unpaid_members: + if not member in os.listdir(WORKDIR+"/impayé"): + # Get member infos + name, numero, email = get_member_infos(member) + + if notify_unpaid(member): + set_file_content(WORKDIR+"/impayé/"+str(member), + str(datetime.datetime.now().strftime("%d/%m/%Y"))) + else: + # Ancient date for the system to be triggered + set_file_content(WORKDIR+"/impayé/"+str(member),"27/09/1983") + BUF.append("* {} (numero {}), {}".format(member, numero, name)) + BUF.append(" COURRIEL NON FONCTIONNEL") + + # Check periodically for unpaid members + for record in os.listdir(WORKDIR+"/impayé"): + last_contact = \ + datetime.datetime.strptime( + get_file_content(WORKDIR+"/impayé/"+record)[0],'%d/%m/%Y') + + # Too old to be a relaunch + if abs(datetime.datetime.now() - last_contact).days > 300: + if notify_unpaid(record): + os.remove(WORKDIR+"/impayé/"+str(record)) + set_file_content(WORKDIR+"/impayé/"+str(record), + str(datetime.datetime.now().strftime("%d/%m/%Y"))) + # Relaunch + elif abs(datetime.datetime.now() - last_contact).days > 30: + renotify_unpaid(record) + os.remove(WORKDIR+"/impayé/"+str(record)) + set_file_content(WORKDIR+"/impayé/"+str(record), + str(datetime.datetime.now().strftime("%d/%m/%Y"))) + + # Clean transited member if unpaid or expired + for record in os.listdir(WORKDIR+"/transition"): + if record in os.listdir(WORKDIR+"/impayé") or \ + record in os.listdir(WORKDIR+"/expiré"): + os.remove(WORKDIR+"/transition/"+record) + +def validate(member): + + # Get infos + request = "SELECT *, l.reference true_reference " +\ + "FROM services_users su " +\ + "INNER JOIN membres m ON m.id = su.id_user " +\ + "INNER JOIN services_fees sf ON sf.id = su.id_fee " +\ + "LEFT JOIN acc_transactions_users tu ON tu.id_service_user = su.id " +\ + "LEFT JOIN acc_transactions_lines l ON l.id_transaction = tu.id_transaction " +\ + "INNER JOIN acc_transactions tr ON tr.id = l.id_transaction " +\ + "WHERE m.id = {} AND l.id_account = 481;".format(member) +# Note: su.id_service = 1 parceque la cotisation correspond au service 1 + + answer = gestion_read(request)["results"][-1] + + print(answer) + + date = datetime.datetime.strptime( + answer["date"],'%Y-%m-%d').strftime("%d/%m/%Y") + filename = "{}_reçu_{}".format( + answer["nom"].replace(" ", "_"), + date.replace("/", ".")) + + BUF.append("* {} (numero {}), {}".format(answer["id"], + answer["numero"], + answer["nom"])) + BUF.append(" COTISATION : {},{}€".format(str(answer["amount"])[:-2], + str(answer["amount"])[-2:])) + BUF.append(" ANNEE CIVILE : {}".format(answer["date"][:4])) + BUF.append(" VALIDATION MEMBRE") + BUF.append("") + + # Generate receipt + latexfile = get_file_content_all("RECU_COTISATION.tex") + latexfile = latexfile.replace("ANNEE-CIVILE", answer["date"][:4]) + latexfile = latexfile.replace("NOM-COTISANT", answer["nom"]) + latexfile = latexfile.replace("STATUT-COTISANT", answer["statut_juridique"]) + latexfile = latexfile.replace("ADRESSE-COTISANT", "{}, {} {}".format( + answer["adresse"], + answer["code_postal"], + answer["ville"])) + latexfile = latexfile.replace("SOMME", "{},{}".format( + str(answer["amount"])[:-2], + str(answer["amount"])[-2:])) + latexfile = latexfile.replace("DATE-VERSEMENT", date) + latexfile = latexfile.replace("MODE-VERSEMENT", answer["true_reference"]) + + try: + os.remove(WORKDIR+"/validé/"+filename+".tex") + except: + pass + set_file_content(WORKDIR+"/validé/"+filename+".tex", latexfile) + os.system("cd {} && pdflatex {}".format(WORKDIR+"/validé/", filename+".tex")) + +def validate_members(): + for record in os.listdir(WORKDIR+"/transition"): + validate(record) def main(): setup_workdir() + check_expired_unpaid() + validate_members() # End of work # Launch summary mail