#!/usr/bin/python3 import argparse import configparser import psycopg2 import datetime import json import pprint # network imports import smtplib from email.mime.text import MIMEText from email.parser import Parser # local imports import fcntoolbox.dolibarr as dolibarr parser = argparse.ArgumentParser() parser.add_argument("selection", type=str, choices=["send-reminders", "report"]) parser.add_argument("-c", "--config", type=str, default="/etc/fcntoolbox/config.ini", help="specify a configuration file") args = parser.parse_args() conf = configparser.RawConfigParser() conf.sections() conf.read(args.config) confdoli = conf['dolibarr'] remindConf = conf['reminder'] s = smtplib.SMTP('localhost') conn = psycopg2.connect(database=confdoli['database'], user=confdoli['user'], password=confdoli['password']) doli = dolibarr.Instance(conn) accounts = list(doli.get_bank_accounts(fields=['iban_prefix', 'bank'])) parsedate = lambda x : datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S") reportAdherents = [] reportBody = [] def getLateMembers(reminder): minKey = "%s_min" % reminder maxKey = "%s_max" % reminder if (not minKey in remindConf) or (not maxKey in remindConf): print("Configuration missing for '%', skipping reminder" % reminder) return list() min = int(remindConf[minKey]) minabs = abs(min) minsign = '+' if min >= 0 else '-' max = int(remindConf[maxKey]) maxabs = abs(max) maxsign = '+' if max >= 0 else '-' rows = ["rowid", "firstname", "lastname", "datefin", "email"] query = """SELECT {} FROM llx_adherent WHERE (datefin {} interval '{} days' > 'now' AND datefin {} interval '{} days' < 'now') AND statut = 1 """ cur = conn.cursor() cur.execute(query.format(",".join(rows), maxsign, maxabs, minsign, minabs)) members = cur.fetchall() members = list(map(lambda member: dict(zip(rows, member)), members)) return members def sendReminders(reminder): global reportAdherents global reportBody lateMembers = getLateMembers(reminder) # Last reminder state remindstate = laststate[reminder] if reminder in laststate else [] # New reminder state state[reminder] = list(map(lambda x : int(x['rowid']), lateMembers)) adherents = list(filter(lambda x: not int(x['rowid']) in remindstate, lateMembers)) remindFormat = open('cotisation-%s.format' % reminder, 'r').read() for adherent in adherents: adherent['rowid'] = int(adherent['rowid']) fdict = adherent.copy() if len(accounts) > 0: account = accounts[0] fdict['bank_account_iban'] = account[0] fdict['bank_account_bank'] = account[1] rawemail = remindFormat.format(**fdict) parsedemail = Parser().parsestr(rawemail) body = parsedemail.get_payload() msg = MIMEText(body) for key, val in parsedemail.items(): msg[key] = val msg['From'] = "tresoriers@listes.franciliens.net" msg['To'] = adherent['email'] if not "Subject" in msg: print("Error: no subject in template email") break if len(body.strip()) == 0: print("Error: no body in template email") break s.send_message(msg) if len(adherents) > 0: reportAdherents += adherents reportBody += [body] if args.selection == 'send-reminders': # Read state with open('cotisation-state.json', 'r') as statefp: laststate = json.load(statefp) state = laststate reminders = ['reminder0', 'reminder1', 'reminder2', 'reminder3'] for reminder in reminders: sendReminders(reminder) reportFormat = open('cotisation-report.format', 'r').read() pp = pprint.PrettyPrinter() if len(reportAdherents) > 0: body = reportFormat.format(adherents = pp.pformat(reportAdherents), template = "\n----------\n".join(reportBody)) msg = MIMEText(body) msg['Subject'] = "Rapport des rappels de cotisation" msg['From'] = "root@franciliens.net" msg['To'] = "tresoriers@listes.franciliens.net" s.send_message(msg) s.quit() # Save state with open('cotisation-state.json', 'w') as statefp: json.dump(state, statefp) elif args.selection == 'report': lateMembers = getLateMembers('reminder3') for member in lateMembers: print(member)