2020-02-21 17:25:53 -05:00
|
|
|
#!/usr/bin/env python3
|
|
|
|
|
|
|
|
from datetime import datetime
|
2020-02-18 19:11:14 -05:00
|
|
|
import MySQLdb
|
2020-02-15 12:08:34 -05:00
|
|
|
import yaml
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-18 19:11:14 -05:00
|
|
|
from common import membershipworks
|
2020-02-25 15:27:08 -05:00
|
|
|
from passwords import MEMBERSHIPWORKS_DB
|
2020-02-21 17:25:53 -05:00
|
|
|
|
|
|
|
|
2020-02-15 12:08:34 -05:00
|
|
|
def insertFromTableMap(table, data, tableMap):
|
2020-02-18 19:11:14 -05:00
|
|
|
def resolveSource(key, value):
|
|
|
|
if type(value) == str:
|
|
|
|
return value
|
|
|
|
elif type(value) == dict and 'source' in value:
|
|
|
|
return value['source']
|
|
|
|
else:
|
|
|
|
return key
|
|
|
|
|
2020-02-15 12:08:34 -05:00
|
|
|
def formatRows(data):
|
|
|
|
for d in data:
|
2020-02-18 19:11:14 -05:00
|
|
|
yield [d.get(resolveSource(k, v)) for k, v in tableMap.items()]
|
|
|
|
|
|
|
|
# TODO: this could probably be done better as a single statement?
|
|
|
|
# note: this only works if in python >= 3.7 where `dict` is ordered
|
2020-02-19 15:40:46 -05:00
|
|
|
c.executemany(
|
|
|
|
'INSERT INTO ' + table + ' (' +
|
|
|
|
','.join(f'`{k}`' for k in tableMap.keys()) +
|
|
|
|
') VALUES (' + ','.join(len(tableMap) * ['%s']) + ') ' +
|
|
|
|
'ON DUPLICATE KEY UPDATE ' +
|
|
|
|
', '.join(f'`{k}`=VALUES(`{k}`)' for k in tableMap.keys()) + ';',
|
|
|
|
list(formatRows(data)))
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-18 19:11:14 -05:00
|
|
|
# TODO: delete non-valid labels
|
2020-02-21 17:25:53 -05:00
|
|
|
def insertLabels(members):
|
2020-02-19 15:24:55 -05:00
|
|
|
for member in members:
|
|
|
|
for label, label_id in membershipworks._parse_flags()['labels'].items():
|
|
|
|
if member[label]:
|
2020-02-19 15:40:46 -05:00
|
|
|
c.execute("""
|
|
|
|
INSERT INTO member_labels (uid, label_id) VALUES (%s, %s)
|
|
|
|
ON DUPLICATE KEY UPDATE
|
|
|
|
uid=VALUES(uid), label_id=VALUES(label_id);""",
|
2020-02-19 15:24:55 -05:00
|
|
|
(member['Account ID'], label_id))
|
|
|
|
else:
|
|
|
|
c.execute('DELETE FROM member_labels WHERE uid=%s && label_id=%s;',
|
|
|
|
(member['Account ID'], label_id))
|
|
|
|
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-15 12:08:34 -05:00
|
|
|
with open('tableMapping.yaml') as f:
|
|
|
|
tableMapping = yaml.load(f, yaml.SafeLoader)
|
2020-02-21 17:25:53 -05:00
|
|
|
|
|
|
|
|
2020-02-25 15:27:08 -05:00
|
|
|
conn = MySQLdb.connect(**MEMBERSHIPWORKS_DB)
|
2020-02-18 19:11:14 -05:00
|
|
|
c = conn.cursor()
|
|
|
|
|
|
|
|
def createDefinitionsFromTableMap(tableMap):
|
|
|
|
def resolveColType(value):
|
|
|
|
if type(value) == dict and 'type' in value:
|
|
|
|
return value['type']
|
|
|
|
else:
|
|
|
|
return 'TEXT'
|
|
|
|
|
|
|
|
return ', '.join([f'`{k}` ' + resolveColType(v)
|
|
|
|
for k, v in tableMap.items()])
|
|
|
|
|
|
|
|
try:
|
2020-02-25 15:27:37 -05:00
|
|
|
print("Creating tables...")
|
2020-02-21 17:25:53 -05:00
|
|
|
c.execute('CREATE TABLE IF NOT EXISTS members (' +
|
2020-02-18 19:11:14 -05:00
|
|
|
createDefinitionsFromTableMap(tableMapping['members']) +
|
|
|
|
') WITH SYSTEM VERSIONING;')
|
2020-02-15 12:08:34 -05:00
|
|
|
|
|
|
|
c.execute("CREATE TABLE IF NOT EXISTS transactions (" +
|
2020-02-18 19:11:14 -05:00
|
|
|
createDefinitionsFromTableMap(tableMapping['transactions']) +
|
|
|
|
", CONSTRAINT `fk_member_uid` FOREIGN KEY (uid) REFERENCES members(uid));")
|
|
|
|
#-- FOREIGN KEY event_id REFERENCES event eid
|
2020-02-21 17:25:53 -05:00
|
|
|
|
|
|
|
c.execute("""CREATE TABLE IF NOT EXISTS labels (
|
2020-02-18 19:11:14 -05:00
|
|
|
label_id CHAR(24) PRIMARY KEY, label TEXT
|
|
|
|
) WITH SYSTEM VERSIONING;""")
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-18 19:11:14 -05:00
|
|
|
c.execute("""CREATE TABLE IF NOT EXISTS member_labels (
|
|
|
|
uid CHAR(24), label_id CHAR(24),
|
|
|
|
PRIMARY KEY(uid, label_id),
|
|
|
|
FOREIGN KEY(uid) REFERENCES members(uid),
|
|
|
|
FOREIGN KEY(label_id) REFERENCES labels(label_id)
|
|
|
|
) WITH SYSTEM VERSIONING;""")
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-25 15:27:37 -05:00
|
|
|
print("Updating labels")
|
|
|
|
c.executemany("""INSERT INTO labels (label, label_id) VALUES (%s, %s)
|
|
|
|
ON DUPLICATE KEY UPDATE
|
|
|
|
label=VALUES(label), label_id=VALUES(label_id);""",
|
|
|
|
membershipworks._parse_flags()['labels'].items())
|
|
|
|
|
|
|
|
print("Getting/Updating members...")
|
2020-02-21 17:25:53 -05:00
|
|
|
members = membershipworks.get_all_members()
|
|
|
|
for m in members:
|
|
|
|
# replace flags by booleans
|
|
|
|
for flag in [dek['lbl'] for dek in membershipworks.org_info['dek']]:
|
|
|
|
if flag in m:
|
|
|
|
m[flag] = m[flag] == flag
|
|
|
|
|
|
|
|
for field_id, field in membershipworks._all_fields().items():
|
|
|
|
# convert checkboxes to real booleans
|
|
|
|
if field.get('typ') == 8 and field['lbl'] in m: # check box
|
|
|
|
m[field['lbl']] = True if m[field['lbl']] == 'Y' else False
|
|
|
|
|
2020-02-15 12:08:34 -05:00
|
|
|
insertFromTableMap('members', members, tableMapping['members'])
|
2020-02-18 19:11:14 -05:00
|
|
|
|
2020-02-21 17:25:53 -05:00
|
|
|
insertLabels(members)
|
|
|
|
|
2020-02-25 15:27:37 -05:00
|
|
|
print("Getting/Updating transactions...")
|
2020-02-21 17:25:53 -05:00
|
|
|
transactions = membershipworks.get_transactions(datetime(2020, 1, 1), datetime.now())
|
2020-02-15 12:08:34 -05:00
|
|
|
insertFromTableMap('transactions', transactions, tableMapping['transactions'])
|
2020-02-21 17:25:53 -05:00
|
|
|
|
2020-02-25 15:27:37 -05:00
|
|
|
print("Committing changes...")
|
2020-02-18 19:11:14 -05:00
|
|
|
conn.commit()
|
|
|
|
|
|
|
|
except Exception as e:
|
|
|
|
print("Transaction failed, rolling back")
|
|
|
|
conn.rollback();
|
|
|
|
raise e
|
|
|
|
|
|
|
|
finally:
|
|
|
|
conn.close()
|
|
|
|
|
|
|
|
# TODO: folders, levels, addons
|