#!/usr/bin/python3 # Libre en Communs's mecene 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="/home/tresorier/.secret/gestion_api_password" WORKDIR="/srv/validation_don.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 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 setup_workdir(): if not os.path.isdir(WORKDIR): os.mkdir(WORKDIR) if not "transition" in os.listdir(WORKDIR): os.mkdir(WORKDIR+"/transition") if not "nouveau" in os.listdir(WORKDIR): os.mkdir(WORKDIR+"/nouveau") if not "validé" in os.listdir(WORKDIR): os.mkdir(WORKDIR+"/validé") 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(record): # Check if notified content = get_file_content_all(WORKDIR+"/transition/"+record).split("\n") if len(content) > 8 and "notified" in content[8]: return # Get infos name, surname, address, postal_code, city, email, amount, mode = \ get_file_content_all(WORKDIR+"/transition/"+record).split("\n")[:8] BUF.append("* {} {}, {} €".format(record, name, amount)) BUF.append(" NOTIFICATION DONATEUR") BUF.append("") mailtext = get_file_content_all(MODALITY_MAIL) + "\n" mailtext = mailtext.replace("NOM_DONNEUR", surname+" "+name) mailtext = mailtext.replace("NUMERO_DON", str(record)) mailtext = mailtext.replace("MONTANT_DON", amount) mailtext = mailtext.replace("MODE_DON", mode) mailheaders = get_file_content_all(MODALITY_MAIL_HEADERS) + "\n" mailheaders = mailheaders.replace("COURRIEL_DONNEUR", email) # Notify sendmail(mailheaders, mailtext) # Indicate as notified with open(WORKDIR+"/transition/"+record, "a") as sfile: sfile.write("notified") def validate(record): # Get infos request = "SELECT * FROM acc_transactions tr " +\ "INNER JOIN acc_transactions_lines l " +\ " ON tr.id = l.id_transaction " +\ "WHERE tr.notes LIKE '%{}%' and id_account = 469".format(record) # Note: su.id_service = 1 parceque la cotisation correspond au service 1 try: answer = gestion_read(request)["results"][-1] except: return False name, surname, address, postal_code, city, email, amount, mode = \ get_file_content_all(WORKDIR+"/transition/"+record).split("\n")[:8] date = datetime.datetime.strptime( answer["date"],'%Y-%m-%d').strftime("%d/%m/%Y") filename = "{}_reçu_{}_{}".format( name, record, date.replace("/", ".")) BUF.append("* {} {}, {} €".format(record, name, "{},{}".format( str(answer["credit"])[:-2], str(answer["credit"])[-2:]))) BUF.append(" VALIDATION DON") BUF.append("") # Generate receipt latexfile = get_file_content_all("RECU_FISCAL.tex") latexfile = latexfile.replace("NUMERO-DON", record) latexfile = latexfile.replace("ANNEE-CIVILE", answer["date"][:4]) latexfile = latexfile.replace("NOM-DONATEUR", name) latexfile = latexfile.replace("STATUT-DONATEUR", "Personne physique") # XXX latexfile = latexfile.replace("ADRESSE-DONATEUR", "{}, {} {}".format( address, postal_code, city)) latexfile = latexfile.replace("SOMME", "{},{}".format( str(answer["credit"])[:-2], str(answer["credit"])[-2:])) latexfile = latexfile.replace("DATE-VERSEMENT", date) latexfile = latexfile.replace("MODE-VERSEMENT", answer["reference"]) latexfile = latexfile.replace("FORME-DON", "Déclaration de don manuel") # XXX latexfile = latexfile.replace("NATURE-DON", "Numéraire") # XXX 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", email) + "\n" mailtext = get_file_content_all(RECEPT_MAIL).replace("DATE-DON", date) + "\n" mailtattach = get_file_content_all(RECEPT_MAIL_ATTACHMENT).replace( "DATE-DON", record + "_" + date.replace("/", ".")) + "\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/"+record) return True def check_record(intent): numero, content = get_file_content_all(intent).split("|") name, surname, address, postal_code, city, email, amount, mode = \ content.split(";")[:8] BUF.append("* {} {}, {} €".format(numero, name+" "+surname, amount)) BUF.append(" NOUVEAU DON") BUF.append("") lines = [ "{}\n{}\n{}\n{}\n{}\n{}\n{}\n{}\n".format( name, surname, address, postal_code, city, email, amount, mode ) ] set_file_content(WORKDIR+"/transition/"+numero, lines) if numero in os.listdir(WORKDIR+"/transition/"): os.remove(intent) def validate_donors(): # Get new for new_intent in os.listdir(WORKDIR+"/nouveau"): check_record(WORKDIR+"/nouveau/"+new_intent) # Validate record for record in os.listdir(WORKDIR+"/transition"): if not validate(record): notify_unpaid(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()