]> git.siccegge.de Git - teilnehmertool.git/blob - teilnehmertool.py
teilnehmertool: quittungs-TeXs auch bauen
[teilnehmertool.git] / teilnehmertool.py
1 #!/usr/bin/python
2 # -*- coding: utf-8 -*-
3
4 import argparse
5 import sqlite3
6 import datetime
7 import csv
8 import string
9 import jinja2
10 import os
11 import os.path
12 import re
13 import sys
14
15 import csv
16
17 conn = None
18
19
20 env = jinja2.Environment(loader=jinja2.FileSystemLoader('templates', encoding='utf-8'))
21
22
23 ## jinja2 TeX espaping from http://flask.pocoo.org/snippets/55/
24 LATEX_SUBS = [
25 (re.compile(r'\\'), r'\\textbackslash{}'),
26 (re.compile(r'([{}_#%&$])'), r'\\\1'),
27 (re.compile(r'~'), r'\~{}'),
28 (re.compile(r'\^'), r'\^{}'),
29 (re.compile(r'"'), r"''"),
30 (re.compile(r'\.\.\.+'), r'\\ldots'),
31 ]
32
33 def escape_tex(value):
34 newval = value
35 for pattern, replacement in LATEX_SUBS:
36 newval = pattern.sub(replacement, newval)
37 return newval
38
39 env.filters['escape_tex'] = escape_tex
40
41
42 ## dont judge me. i don't see any good way sadly
43 VERANSTALTUNGSLEITER = {
44 }
45
46 def is_veranstaltungsleiter(row):
47 if VERANSTALTUNGSLEITER.has_key(row['username']):
48 return True
49 return False
50
51
52 def create_helfer_nametags(csvpath, outdir='helfer_nametags'):
53 template = env.get_template('nametag.svg')
54
55 with open(csvpath, 'r') as csvfile:
56 csvreader = csv.DictReader(csvfile, delimiter=',', quotechar='"')
57 uni = "FAU Erlangen"
58
59 for row in csvreader:
60 if is_veranstaltungsleiter(row):
61 nick = "%s %s" % (VERANSTALTUNGSLEITER[row['username']][0], VERANSTALTUNGSLEITER[row['username']][1])
62 with open(os.path.join(outdir, "%s.svg" % nick), 'w') as f:
63 f.write(template.render(nick=nick.decode('utf-8'), uni1=uni.decode('utf-8')).encode('utf-8'))
64 nick = "%s" % (row['username'])
65
66 with open(os.path.join(outdir, "%s.svg" % nick), 'w') as f:
67 f.write(template.render(nick=nick.decode('utf-8'), uni1=uni.decode('utf-8')).encode('utf-8'))
68
69
70 def import_teilnehmer(input):
71 ids = set([ i[0] for i in conn.execute('SELECT id FROM teilnehmer').fetchall() ])
72
73 with open(input) as f:
74 reader = csv.reader(f, delimiter=';', quotechar='"')
75 for row in reader:
76 if row[0] == '#':
77 continue
78 if not int(row[0]) in ids:
79 print "Importing %s" % (row, )
80 conn.execute("INSERT INTO teilnehmer VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)",
81 row[:-2] + ['Kein T-Shirt', 'Kein Pulli'] + row[-2:] + [0, 0, 0, "", "false"])
82
83 conn.commit()
84
85 def mark_pay(outdir):
86 betrag = int(raw_input("Betrag: "))
87
88 template = env.get_template('eingangsbestaetigung.eml')
89
90 while True:
91 uid = raw_input("User: ")
92 if uid == "":
93 break
94 uid = int(uid)
95 vorname, nachname, email, bezahlt = \
96 conn.execute("SELECT vorname, nachname, email, bezahlt FROM teilnehmer WHERE id = ?", [uid]).fetchone()
97
98 if bezahlt == betrag:
99 continue
100
101 conn.execute("UPDATE teilnehmer SET bezahlt = ? WHERE id = ?", [betrag, uid])
102
103
104 with open(os.path.join(outdir, email), 'w') as f:
105 f.write(template.render(vorname=vorname.decode('utf-8'),
106 nachname=nachname.decode('utf-8'),
107 email=email.decode('utf-8'),
108 betrag=betrag).encode('utf-8'))
109
110 conn.commit()
111
112 def create_mail(outdir='output'):
113 def gen_rechnung(tshirt, zipper):
114 preis = 25
115 kosten = u""
116 kosten += u"%s | %s\n" % (u" Konferenzbeitrag".ljust(30), "25.00")
117 kosten += u"%s | %s\n" % ((u" T-Shirt (Größe %s)" % tshirt).ljust(30), " 0.00")
118 if zipper != 'Kein Pulli':
119 kosten += u"%s | %s\n" % ((u" Kapuzenzipper (Größe %s)" % zipper).ljust(30), "25.00")
120 preis += 25
121 kosten += ' '*2 + 29*'-' + '+' + 6*'-' + '\n'
122 kosten += u"%s | %s\n" % (u" Summe".ljust(30), "%2d.00" % preis)
123
124 return kosten, preis
125
126 def gen_token(id, vorname, nachname):
127 return u"%s-%s-%s" % (id, nachname.decode('utf-8').upper(), vorname.decode('utf-8').upper())
128
129 template = env.get_template('teilnehmerbeitrag.eml')
130
131 for id, vorname, nachname, email, tshirt, zipper in \
132 conn.execute("SELECT id, vorname, nachname, email, tshirt, zipper FROM teilnehmer WHERE emailsent = 0"):
133
134 rechnung, preis = gen_rechnung(tshirt, zipper)
135
136 with open(os.path.join(outdir, email), 'w') as f:
137 f.write(template.render(vorname=vorname.decode('utf-8'),
138 nachname=nachname.decode('utf-8'),
139 email=email.decode('utf-8'),
140 token=gen_token(id, vorname, nachname),
141 rechnung=rechnung).encode('utf-8'))
142
143 conn.execute("UPDATE teilnehmer set emailsent = ?, betrag = ? WHERE id = ?", [datetime.datetime.now().isoformat(),
144 preis, id])
145 conn.commit()
146
147 def create_remind(outdir='output'):
148 def gen_rechnung(tshirt, zipper):
149 preis = 25
150 kosten = u""
151 kosten += u"%s | %s\n" % (u" Konferenzbeitrag".ljust(30), "25.00")
152 kosten += u"%s | %s\n" % ((u" T-Shirt (Größe %s)" % tshirt).ljust(30), " 0.00")
153 if zipper != 'Kein Pulli':
154 kosten += u"%s | %s\n" % ((u" Kapuzenzipper (Größe %s)" % zipper).ljust(30), "25.00")
155 preis += 25
156 kosten += ' '*2 + 29*'-' + '+' + 6*'-' + '\n'
157 kosten += u"%s | %s\n" % (u" Summe".ljust(30), "%2d.00" % preis)
158
159 return kosten, preis
160
161 def gen_token(id, vorname, nachname):
162 return u"%s-%s-%s" % (id, nachname.decode('utf-8').upper(), vorname.decode('utf-8').upper())
163
164 template = env.get_template('erinnerung.eml')
165
166 for id, vorname, nachname, email, tshirt, zipper in \
167 conn.execute("SELECT id, vorname, nachname, email, tshirt, zipper FROM teilnehmer " +
168 "WHERE bezahlt < 25 AND datetime(emailsent) < datetime(?)",
169 [(datetime.datetime.now() - datetime.timedelta(14)).isoformat()]):
170
171 rechnung, preis = gen_rechnung(tshirt, zipper)
172
173 with open(os.path.join(outdir, email), 'w') as f:
174 f.write(template.render(vorname=vorname.decode('utf-8'),
175 nachname=nachname.decode('utf-8'),
176 email=email.decode('utf-8'),
177 token=gen_token(id, vorname, nachname),
178 rechnung=rechnung).encode('utf-8'))
179
180 conn.execute("UPDATE teilnehmer set emailsent = ?, betrag = ? WHERE id = ?", [datetime.datetime.now().isoformat(),
181 preis, id])
182 conn.commit()
183
184
185 def create_nametag(outdir='output'):
186 template = env.get_template('nametag.svg')
187
188 for teiln_id, vorname, nachname, namensschild, hochschule, dochned in \
189 conn.execute("SELECT id, vorname, nachname, namensschild, hochschule, dochned FROM teilnehmer"):
190
191 if dochned != "false":
192 print >> sys.stderr, "not generating %s %s (id %s), because abgemeldet" % (vorname, nachname, teiln_id)
193 continue
194
195 with open(os.path.join(outdir, "%s.svg" % teiln_id), 'w') as f:
196 f.write(template.render(name=u"%s %s" % (vorname.decode('utf-8'),
197 nachname.decode('utf-8')),
198 nick=namensschild.decode('utf-8'),
199 uni1=hochschule.decode('utf-8')).encode('utf-8'))
200
201
202 def create_teilnehmer_list(outdir = 'output'):
203 template_full = env.get_template('teilnehmerliste.tex')
204 template_pack = env.get_template('packliste.tex')
205 template_quittung = env.get_template('quittung.tex')
206
207 i = 0
208 teilnehmer = []
209 for vor, nach, nick, hochschule, betrag, bezahlt, shirtsize, zippersize, dochned, comment in \
210 conn.execute("SELECT vorname, nachname, namensschild, hochschule, betrag, bezahlt, tshirt, zipper, dochned, orga_comment FROM teilnehmer ORDER BY UPPER(hochschule) ASC, UPPER(nachname) ASC"):
211
212 vor = vor.decode('utf8')
213 nach = nach.decode('utf8')
214 nick = nick.decode('utf8')
215 hochschule = hochschule.decode('utf8')
216 ## betrag ist schon int
217 ## bezahlt ist schon int
218 shirtsize = shirtsize.decode('utf8')
219 if re.match("kein", shirtsize, flags=re.IGNORECASE):
220 shirtsize = ""
221
222 zippersize = zippersize.decode('utf8')
223 if re.match("kein", zippersize, flags=re.IGNORECASE):
224 zippersize = ""
225
226 ## string to bool..
227 if dochned == "false":
228 will_attend = True
229 else:
230 will_attend = False
231
232 comment = comment.decode('utf8')
233
234 teilnehmer.append({'vorname': vor, 'nachname': nach,
235 'hochschule': hochschule, 'nick': nick, 'betrag': betrag, 'bezahlt':
236 bezahlt, 'shirtsize': shirtsize, 'zippersize': zippersize,
237 'will_attend': will_attend, 'comment': comment})
238
239 if will_attend:
240 with open(os.path.join(outdir, ("%03d_quittung_%s_%s.tex" % (i, vor, nach))), 'w') as out:
241 out.write(template_quittung.render(vorname=vor, nachname=nach).encode('utf-8'))
242
243 i = i+1
244
245
246 with open(os.path.join(outdir, "teilnehmerliste.tex"), 'w') as out:
247 out.write(template_full.render(teilnehmer=teilnehmer).encode('utf-8'))
248
249 with open(os.path.join(outdir, "packliste.tex"), 'w') as out:
250 out.write(template_pack.render(teilnehmer=teilnehmer).encode('utf-8'))
251
252
253
254 def create_bmbf_list(outdir = 'output'):
255 template = env.get_template('bmbf-unterschriftenliste.tex')
256
257
258 teilnehmer = []
259 i = 1
260 for vor, nach, hochschule in \
261 conn.execute("SELECT vorname, nachname, hochschule FROM teilnehmer ORDER BY UPPER(nachname) ASC"):
262
263 vor = vor.decode('utf8')
264 nach = nach.decode('utf8')
265 hochschule = hochschule.decode('utf8')
266
267 teilnehmer.append({'vorname': vor, 'nachname': nach, 'num': i, 'hochschule': hochschule})
268 i = i+1
269
270
271 with open(os.path.join(outdir, "bmbf-unterschriftenliste.tex"), 'w') as out:
272 out.write(template.render(teilnehmer=teilnehmer).encode('utf-8'))
273
274
275 def main():
276 parser = argparse.ArgumentParser(description="Ultimate Teilnehmertool")
277
278 # Modus
279 group = parser.add_mutually_exclusive_group(required=True)
280 group.add_argument('--importcsv', action='store_true',
281 help='Importiere neue Teilnehmer aus CSV')
282 group.add_argument('--nametag', action='store_true',
283 help='Generiere Nametags')
284 group.add_argument('--email', action='store_true',
285 help='Generiere E-Mails mit Überweisungsinformationen')
286 group.add_argument('--pay', action='store_true',
287 help='Speichere Zahlungseingang')
288 group.add_argument('--remind', action='store_true',
289 help='Generiere Zahlungsaufforderungserinnerung')
290 group.add_argument('--bmbf', action='store_true',
291 help='Generiere BMBF-Unterschriftenliste')
292 group.add_argument('--liste', action='store_true',
293 help='Generiere Teilnehmerübersichtsliste')
294 group.add_argument('--helfer', action='store_true',
295 help='Generiere Helfer-Nametags aus helfer.csv')
296 group.add_argument('--quittungen', action='store_true',
297 help='Generiere Quittungen für Teilnehmer')
298
299 # Argumente
300 parser.add_argument('--db', default='teilnehmer.sqlite',
301 help='Teilnehmerdatenbank')
302 parser.add_argument('-i', '--input',
303 help='Eingabedatei')
304 parser.add_argument('-o', '--output', default='output',
305 help='Ausgabeverzeichnis')
306
307 args = parser.parse_args()
308
309 global conn
310 conn = sqlite3.connect(args.db)
311 conn.text_factory = str
312 conn.row_factory = sqlite3.Row
313 conn.execute('pragma encoding = "UTF-8";')
314
315 if args.nametag or args.email or args.pay or args.remind or args.bmbf or \
316 args.liste or args.helfer or args.quittungen:
317 assert(args.output)
318 if not os.path.exists(args.output):
319 os.mkdir(args.output)
320
321 if args.nametag:
322 create_nametag(args.output)
323 elif args.email:
324 create_mail(args.output)
325 elif args.pay:
326 mark_pay(args.output)
327 elif args.remind:
328 create_remind(args.output)
329 elif args.bmbf:
330 create_bmbf_list(args.output)
331 elif args.liste:
332 create_teilnehmer_list(args.output)
333 elif args.helfer:
334 assert(args.input)
335 create_helfer_nametags(args.input, args.output)
336 elif args.quittungen:
337 create_teilnehmer_quittungen(args.output)
338
339 elif args.importcsv:
340 assert(args.input)
341 import_teilnehmer(args.input)
342
343 if __name__ == '__main__':
344 main()
345
346 # vim: set expandtab :