From bd88dfc4bf81103dd987aed3c4c8bb80f6203c02 Mon Sep 17 00:00:00 2001 From: Adrien Bourmault Date: Thu, 15 Sep 2022 11:09:29 +0200 Subject: [PATCH] =?UTF-8?q?WIP:=20contr=C3=B4le=20des=20dons?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- controle_don/mail_instructions.txt | 37 ++++ controle_don/mail_instructions_headers.txt | 7 + controle_don/mail_recap_header.txt | 6 + controle_don/mail_recu.txt | 13 ++ controle_don/mail_recu_attachment.txt | 4 + controle_don/mail_recu_headers | 11 + controle_don/main.py | 222 +++++++++++++++++++++ 7 files changed, 300 insertions(+) create mode 100644 controle_don/mail_instructions.txt create mode 100644 controle_don/mail_instructions_headers.txt create mode 100644 controle_don/mail_recap_header.txt create mode 100644 controle_don/mail_recu.txt create mode 100644 controle_don/mail_recu_attachment.txt create mode 100644 controle_don/mail_recu_headers create mode 100755 controle_don/main.py diff --git a/controle_don/mail_instructions.txt b/controle_don/mail_instructions.txt new file mode 100644 index 0000000..044076a --- /dev/null +++ b/controle_don/mail_instructions.txt @@ -0,0 +1,37 @@ +Bonjour NOM_DONNEUR et merci de votre générosité ! + +Suite à votre soumission de notre formulaire sur https://don.a-lec.org, +je reviens vers vous pour vous informer des modalités de règlement de +votre don numéro NUMERO_DON d'un montant de MONTANT_DON €. + +Les moyens de paiement acceptés sont: espèces, chèques et virement bancaire. +Vous avez indiqué régler par MODE_DON. Si toutefois vous souhaitez changer de +mode de paiement, merci de nous en informer en réponse à ce courriel. + + +Pour le paiement par chèque à l'ordre de Libre en Communs, ainsi que le paiement +en espèces, merci d'expédier votre courrier à l'adresse suivante: + +ASSOCIATION LIBRE EN COMMUNS +13 RUE SULLY +94210 SAINT MAUR DES FOSSÉS + + +Pour le paiement par virement bancaire, merci d'émettre votre virement à +destination de l'IBAN ci-dessous. MERCI D'INDIQUER VOTRE NUMERO DE DON EN +COMMENTAIRE OU REFERENCE DE VOTRE VIREMENT. + +IBAN: FR7610278061690002212870186 +BIC: CMCIFR2A +Domiciliation: CCM DU PLATEAU BRIARD + + +Vous remerciant encore de votre engagement, +Librement, + +-- +Adrien Bourmault +Trésorier de Libre en Communs +GPG: 0980e827cb47fbb9 +- +Association Libre en Communs \ No newline at end of file diff --git a/controle_don/mail_instructions_headers.txt b/controle_don/mail_instructions_headers.txt new file mode 100644 index 0000000..85e1249 --- /dev/null +++ b/controle_don/mail_instructions_headers.txt @@ -0,0 +1,7 @@ +Content-Language: fr +From: =?UTF-8?Q?Tr=c3=a9sorier_de_Libre_en_Communs?= +To: +Subject: =?UTF-8?Q?Libre_en_Communs_:_modalit=c3=a9s_de_r=c3=a8glement_de_vo?= + =?UTF-8?Q?tre_don?= +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable \ No newline at end of file diff --git a/controle_don/mail_recap_header.txt b/controle_don/mail_recap_header.txt new file mode 100644 index 0000000..046a967 --- /dev/null +++ b/controle_don/mail_recap_header.txt @@ -0,0 +1,6 @@ +From: tresorier@a-lec.org +To: tresorier@a-lec.org +Subject: Suivi automatique des dons +MIME-Version: 1.0 +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable \ No newline at end of file diff --git a/controle_don/mail_recu.txt b/controle_don/mail_recu.txt new file mode 100644 index 0000000..bc3a7e8 --- /dev/null +++ b/controle_don/mail_recu.txt @@ -0,0 +1,13 @@ +Bonjour, + +Veuillez trouver ci-joint votre reçu au titre de votre don à l'association +Libre en Communs du DATE-DON. + +Librement, + +-- +Adrien Bourmault +Trésorier de Libre en Communs +GPG: 0980e827cb47fbb9 +- +Association Libre en Communs \ No newline at end of file diff --git a/controle_don/mail_recu_attachment.txt b/controle_don/mail_recu_attachment.txt new file mode 100644 index 0000000..ca521e6 --- /dev/null +++ b/controle_don/mail_recu_attachment.txt @@ -0,0 +1,4 @@ +--------------3yxkFgv0AINs5nd0i6BJrWaV +Content-Type: application/pdf; name="Recu_don_DATE-DON.pdf" +Content-Disposition: attachment; filename="Recu_don_DATE-DON.pdf" +Content-Transfer-Encoding: base64 \ No newline at end of file diff --git a/controle_don/mail_recu_headers b/controle_don/mail_recu_headers new file mode 100644 index 0000000..c65f932 --- /dev/null +++ b/controle_don/mail_recu_headers @@ -0,0 +1,11 @@ +Content-Language: fr +From: =?UTF-8?Q?Tr=c3=a9sorier_de_Libre_en_Communs?= +To: +Subject: =?UTF-8?Q?=5bTr=c3=a9sorerie=5d_Re=c3=a7u_pour_votre_don_pour_Libre_en_Communs?= +Mime-Version: 1.0 +Content-Type: multipart/mixed; boundary="------------3yxkFgv0AINs5nd0i6BJrWaV" + +This is a multi-part message in MIME format. +--------------3yxkFgv0AINs5nd0i6BJrWaV +Content-Type: text/plain; charset="UTF-8" +Content-Transfer-Encoding: quoted-printable \ No newline at end of file diff --git a/controle_don/main.py b/controle_don/main.py new file mode 100755 index 0000000..f1f35a1 --- /dev/null +++ b/controle_don/main.py @@ -0,0 +1,222 @@ +#!/usr/bin/python3 + +# Libre en Communs's cotisation control program +# Copyright (C) 2022 Libre en Communs + +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as +# published by the Free Software Foundation, either version 3 of the +# License, or (at your option) any later version. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. + +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see . + +import os, requests, json, datetime, shutil, quopri, subprocess, base64 +from requests.auth import HTTPBasicAuth +from requests.auth import HTTPDigestAuth + + +VERSION="1.0.0" +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" +RECEPT_MAIL_HEADERS="mail_recu_headers.txt" +RECEPT_MAIL_ATTACHMENT="mail_recu_attachment.txt" +SUMMARY_MAIL="mail_recap_header.txt" +SENDMAIL_LOCATION = "/usr/sbin/sendmail" # sendmail location +BUF=[] + +# gestion_read("SELECT * 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 \ +# WHERE m.id = 3 AND l.id_account = 481;") + +def gestion_get_secret(): + with open(GESTION_SECRET_FILE) as sfile: + return sfile.readline().replace("\n", "") + +def git_get_secret(): + with open(GIT_SECRET_FILE) as sfile: + return sfile.readline().replace("\n", "") + +def get_file_content(filename): + with open(filename) as sfile: + return sfile.readlines() + +def get_file_content_all(filename): + with open(filename) as sfile: + return sfile.read() + +def set_file_content(filename, lines): + with open(filename, "x") as sfile: + return sfile.writelines(lines) + +def gestion_read(req): + response = requests.post('https://gestion.a-lec.org/api/sql/', + auth = HTTPBasicAuth('api666', gestion_get_secret()), + data = req) + return response.json() + +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()}, + params = req) + return response.json() + +def git_xmpp_ticket_create(req): + response = requests.post('https://git.a-lec.org/api/v4/projects/44/issues', + headers={'PRIVATE-TOKEN' : git_get_secret()}, + data = req) + return response.json() + +def setup_workdir(): + if not os.path.isdir(WORKDIR): + os.mkdir(WORKDIR) + if not "impayé" in os.listdir(WORKDIR): + os.mkdir(WORKDIR+"/impayé") + if not "expiré" in os.listdir(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')) + subprocess.run([SENDMAIL_LOCATION, "-t", "-oi"], input=msg) + +def sendmail_with_attachment(headers, data, attachment_header, attachment, ending): + msg = bytes(headers + "\n", 'utf-8') \ + + quopri.encodestring(bytes(data, 'utf-8')) \ + + bytes(attachment_header + "\n", 'utf-8') \ + + base64.b64encode(attachment) \ + + bytes(ending, 'utf-8') + + subprocess.run([SENDMAIL_LOCATION, "-t", "-oi"], input=msg) + +def notify_unpaid(donor): + # Get infos + pass + + BUF.append("* {} {}, {} €".format(numero, name, amount)) + BUF.append(" NOTIFICATION DONATEUR") + BUF.append("") + + mailtext = get_file_content_all(MODALITY_MAIL) + "\n" + mailtext = mailtext.replace("NOM_DONNEUR", name) + mailtext = mailtext.replace("NUMERO_DON", str(numero)) + mailtext = mailtext.replace("MONTANT_DON", amount) + mailtext = mailtext.replace("MODE_DON", year) + mailheaders = get_file_content_all(MODALITY_MAIL_HEADERS) + "\n" + mailheaders = mailheaders.replace("COURRIEL_DONNEUR", email) + + sendmail(mailheaders, mailtext) + +def validate(donor): + + # 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(donor) +# Note: su.id_service = 1 parceque la cotisation correspond au service 1 + + try: + answer = gestion_read(request)["results"][-1] + except: + print(gestion_read(request)) + raise(Exception) + + date = datetime.datetime.strptime( + answer["date"],'%Y-%m-%d').strftime("%d/%m/%Y") + + filename = "{}_reçu_{}".format( + answer["nom"].replace(" ", "_"), + date.replace("/", ".")) + + BUF.append("* {} {}, {} €".format(numero, name, amount)) + BUF.append(" VALIDATION DON") + BUF.append("") + + # Generate receipt + latexfile = get_file_content_all("RECU_COTISATION.tex") + latexfile = latexfile.replace("ANNEE-CIVILE", answer["date"][:4]) + latexfile = latexfile.replace("NOM-DONATEUR", answer["nom"]) + latexfile = latexfile.replace("STATUT-DONATEUR", answer["statut_juridique"]) + latexfile = latexfile.replace("ADRESSE-DONATEUR", "{}, {} {}".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"]) + latexfile = latexfile.replace("FORME-DON", answer["true_reference"]) + latexfile = latexfile.replace("NATURE-DON", 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")) + + # Preparing mail + mailheaders = get_file_content_all(RECEPT_MAIL_HEADERS).replace("COURRIEL-DON", + answer["email"]) + "\n" + mailtext = get_file_content_all(RECEPT_MAIL) + "\n" + mailtattach = get_file_content_all(RECEPT_MAIL_ATTACHMENT) + "\n" + + # Opening PDF file as binary + attachment = open(WORKDIR+"/validé/"+filename+".pdf", "rb") + data = attachment.read() + attachment.close() + + ending = "--------------3yxkFgv0AINs5nd0i6BJrWaV--" + + sendmail_with_attachment(mailheaders, mailtext, mailtattach, data, ending) + + # The end + os.remove(WORKDIR+"/transition/"+donor) + +def validate_donors(): + for record in os.listdir(WORKDIR+"/transition"): + validate(record) + +def main(): + setup_workdir() + #GET DATA() + validate_donors() + + # End of work + # Launch summary mail + mailheaders = get_file_content_all(SUMMARY_MAIL) + "\n" + mailtext = "" + + is_sendable = False; + for line in BUF: + mailtext += line + "\n" + is_sendable = True; + print(line) + + if is_sendable: + sendmail(mailheaders, mailtext) + +## Bootstrap +if __name__ == '__main__': + main()