fcn-cotisation 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133
  1. #!/usr/bin/python3
  2. import argparse
  3. import configparser
  4. import psycopg2
  5. import datetime
  6. import json
  7. import pprint
  8. # network imports
  9. import smtplib
  10. from email.mime.text import MIMEText
  11. from email.parser import Parser
  12. parser = argparse.ArgumentParser()
  13. parser.add_argument("selection", type=str,
  14. choices=["send-reminders", "report"])
  15. parser.add_argument("-c", "--config", type=str,
  16. default="/etc/fcntoolbox/config.ini",
  17. help="specify a configuration file")
  18. args = parser.parse_args()
  19. conf = configparser.RawConfigParser()
  20. conf.sections()
  21. conf.read(args.config)
  22. confdoli = conf['dolibarr']
  23. remindConf = conf['reminder']
  24. s = smtplib.SMTP('localhost')
  25. conn = psycopg2.connect(database=confdoli['database'],
  26. user=confdoli['user'], password=confdoli['password'])
  27. parsedate = lambda x : datetime.datetime.strptime(x, "%Y-%m-%d %H:%M:%S")
  28. reportAdherents = []
  29. reportBody = []
  30. def getLateMembers(reminder):
  31. minKey = "%s_min" % reminder
  32. maxKey = "%s_max" % reminder
  33. if (not minKey in remindConf) or (not maxKey in remindConf):
  34. print("Configuration missing for '%', skipping reminder" % reminder)
  35. return list()
  36. min = int(remindConf[minKey])
  37. minabs = abs(min)
  38. minsign = '+' if min >= 0 else '-'
  39. max = int(remindConf[maxKey])
  40. maxabs = abs(max)
  41. maxsign = '+' if max >= 0 else '-'
  42. rows = ["rowid", "firstname", "lastname", "datefin", "email"]
  43. query = """SELECT {} FROM llx_adherent
  44. WHERE (datefin {} interval '{} days' > 'now'
  45. AND datefin {} interval '{} days' < 'now')
  46. AND statut = 1 """
  47. cur = conn.cursor()
  48. cur.execute(query.format(",".join(rows), maxsign, maxabs, minsign, minabs))
  49. members = cur.fetchall()
  50. members = list(map(lambda member: dict(zip(rows, member)), members))
  51. return members
  52. def sendReminders(reminder):
  53. global reportAdherents
  54. global reportBody
  55. lateMembers = getLateMembers(reminder)
  56. # Last reminder state
  57. remindstate = laststate[reminder] if reminder in laststate else []
  58. # New reminder state
  59. state[reminder] = list(map(lambda x : int(x['rowid']), lateMembers))
  60. adherents = list(filter(lambda x: not int(x['rowid']) in remindstate, lateMembers))
  61. remindFormat = open('cotisation-%s.format' % reminder, 'r').read()
  62. for adherent in adherents:
  63. adherent['rowid'] = int(adherent['rowid'])
  64. # adherent['datefin'] = parsedate(adherent['datefin'])
  65. rawemail = remindFormat.format(**adherent)
  66. parsedemail = Parser().parsestr(rawemail)
  67. body = parsedemail.get_payload()
  68. msg = MIMEText(body)
  69. for key, val in parsedemail.items():
  70. msg[key] = val
  71. msg['From'] = "tresoriers@listes.franciliens.net"
  72. msg['To'] = adherent['email']
  73. if not "Subject" in msg:
  74. print("Error: no subject in template email")
  75. break
  76. if len(body.strip()) == 0:
  77. print("Error: no body in template email")
  78. break
  79. s.send_message(msg)
  80. if len(adherents) > 0:
  81. reportAdherents += adherents
  82. reportBody += [body]
  83. if args.selection == 'send-reminders':
  84. # Read state
  85. with open('cotisation-state.json', 'r') as statefp:
  86. laststate = json.load(statefp)
  87. state = laststate
  88. reminders = ['reminder0', 'reminder1', 'reminder2', 'reminder3']
  89. for reminder in reminders:
  90. sendReminders(reminder)
  91. reportFormat = open('cotisation-report.format', 'r').read()
  92. pp = pprint.PrettyPrinter()
  93. if len(reportAdherents) > 0:
  94. body = reportFormat.format(adherents = pp.pformat(reportAdherents), template = "\n----------\n".join(reportBody))
  95. msg = MIMEText(body)
  96. msg['Subject'] = "Rapport des rappels de cotisation"
  97. msg['From'] = "root@franciliens.net"
  98. msg['To'] = "tresoriers@listes.franciliens.net"
  99. s.send_message(msg)
  100. s.quit()
  101. # Save state
  102. with open('cotisation-state.json', 'w') as statefp:
  103. json.dump(state, statefp)
  104. elif args.selection == 'report':
  105. lateMembers = getLateMembers('reminder3')
  106. for member in lateMembers:
  107. print(member)