Move old scripts into scripts/ directory
This commit is contained in:
24
apiserver/scripts/clean_member_names.py
Executable file
24
apiserver/scripts/clean_member_names.py
Executable file
@@ -0,0 +1,24 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
from apiserver.api import models, old_models, utils
|
||||
|
||||
members = models.Member.objects.all()
|
||||
|
||||
for m in members:
|
||||
first_name = m.first_name
|
||||
last_name = m.last_name
|
||||
preferred_name = m.preferred_name
|
||||
|
||||
print('Updating:', first_name, last_name, '-->', first_name.title(), last_name.title())
|
||||
|
||||
models.Member.objects.filter(id=m.id).update(
|
||||
first_name=first_name.title().strip(),
|
||||
last_name=last_name.title().strip(),
|
||||
preferred_name=preferred_name.title().strip(),
|
||||
)
|
||||
|
||||
print('Done.')
|
40
apiserver/scripts/delete_addresses.py
Executable file
40
apiserver/scripts/delete_addresses.py
Executable file
@@ -0,0 +1,40 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
from apiserver.api import models
|
||||
|
||||
print('Deleting member object addresses...')
|
||||
|
||||
result = models.Member.objects.update(
|
||||
street_address='',
|
||||
postal_code='',
|
||||
city='',
|
||||
)
|
||||
|
||||
print(result, 'rows affected')
|
||||
print()
|
||||
|
||||
print('Scrubbing history...')
|
||||
|
||||
result = models.Member.history.update(
|
||||
street_address='',
|
||||
postal_code='',
|
||||
city='',
|
||||
)
|
||||
|
||||
print(result, 'rows affected')
|
||||
print()
|
||||
|
||||
print('Deleting historical changes...')
|
||||
|
||||
address_fields = ['street_address', 'postal_code', 'city']
|
||||
result = models.HistoryChange.objects.filter(field__in=address_fields).update(
|
||||
old='',
|
||||
new='',
|
||||
)
|
||||
|
||||
print(result, 'rows affected')
|
||||
print()
|
||||
|
||||
print('Done.')
|
9
apiserver/scripts/delete_old_backups.sh
Executable file
9
apiserver/scripts/delete_old_backups.sh
Executable file
@@ -0,0 +1,9 @@
|
||||
#!/bin/bash
|
||||
|
||||
# be safe
|
||||
set -euf -o pipefail
|
||||
|
||||
# test these carefully
|
||||
#find "${backup_folder}" -mindepth 1 -type d -print
|
||||
#find "${backup_folder}" -mindepth 1 -type d -ctime +14 -print
|
||||
#find "${backup_folder}" -mindepth 1 -type d -ctime +14 -exec rm -r {} \;
|
13
apiserver/scripts/delete_usagetracks.py
Executable file
13
apiserver/scripts/delete_usagetracks.py
Executable file
@@ -0,0 +1,13 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
from apiserver.api import models
|
||||
|
||||
indexs = models.HistoryIndex.objects.filter(object_name='UsageTrack')
|
||||
count = indexs.delete()
|
||||
print(count, 'indexs deleted')
|
||||
|
||||
changes = models.HistoryChange.objects.filter(field='num_seconds')
|
||||
count = changes.delete()
|
||||
print(count, 'changes deleted')
|
13
apiserver/scripts/export_member_addresses.py
Executable file
13
apiserver/scripts/export_member_addresses.py
Executable file
@@ -0,0 +1,13 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
members = models.Member.objects.all()
|
||||
|
||||
writer = csv.writer(sys.stdout)
|
||||
|
||||
for m in members:
|
||||
writer.writerow([m.id, m.first_name, m.last_name, m.street_address, m.city, m.postal_code])
|
24
apiserver/scripts/export_member_statuses.py
Executable file
24
apiserver/scripts/export_member_statuses.py
Executable file
@@ -0,0 +1,24 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
members = models.Member.objects.all()
|
||||
|
||||
writer = csv.writer(sys.stdout)
|
||||
|
||||
def color(status):
|
||||
if status in ['Prepaid', 'Current']:
|
||||
return 'Green'
|
||||
elif status == 'Due':
|
||||
return 'Yellow'
|
||||
elif status == 'Overdue':
|
||||
return 'Red'
|
||||
else:
|
||||
return 'Black'
|
||||
|
||||
for m in members:
|
||||
status = 'Former Member' if m.paused_date else m.status
|
||||
writer.writerow([m.id, m.first_name, m.last_name, status, color(status)])
|
24
apiserver/scripts/gen_card_photos.py
Executable file
24
apiserver/scripts/gen_card_photos.py
Executable file
@@ -0,0 +1,24 @@
|
||||
# Generates card photos for existing members with photos
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
from apiserver.api import models, utils
|
||||
|
||||
members = models.Member.objects
|
||||
members = members.filter(photo_large__isnull=False)
|
||||
members = members.filter(card_photo__isnull=True)
|
||||
|
||||
print('Count:', members.count())
|
||||
|
||||
for m in members:
|
||||
print('Processing', m.first_name, m.last_name)
|
||||
|
||||
m.card_photo = utils.gen_card_photo(m)
|
||||
print(m.card_photo)
|
||||
|
||||
m.save()
|
||||
|
||||
print('Done.')
|
||||
|
3
apiserver/scripts/gen_old_models.sh
Executable file
3
apiserver/scripts/gen_old_models.sh
Executable file
@@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
|
||||
python manage.py inspectdb --database old_portal | sed 's/CharField/TextField/g' > apiserver/api/old_models.py
|
54
apiserver/scripts/import_card_scans.py
Executable file
54
apiserver/scripts/import_card_scans.py
Executable file
@@ -0,0 +1,54 @@
|
||||
# Expects a scans.csv of the historical scans in format:
|
||||
# date,card_number
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from datetime import datetime, timedelta
|
||||
from apiserver.api import models
|
||||
from django.utils.timezone import now, pytz
|
||||
|
||||
def today_alberta_tz():
|
||||
return datetime.now(pytz.timezone('America/Edmonton')).date()
|
||||
|
||||
days = {}
|
||||
|
||||
date = datetime(2020, 3, 7).date()
|
||||
while date <= today_alberta_tz():
|
||||
days[str(date)] = set()
|
||||
date += timedelta(days=1)
|
||||
|
||||
print('Initialized with:')
|
||||
print(days)
|
||||
|
||||
with open('scans.csv', newline='') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
datetime_obj = datetime.strptime(row['date'], "%Y-%m-%d %H:%M:%S")
|
||||
datetime_obj_utc = datetime_obj.replace(tzinfo=pytz.timezone('UTC'))
|
||||
date = datetime_obj_utc.astimezone(pytz.timezone('America/Edmonton'))
|
||||
|
||||
card = row['card_number']
|
||||
|
||||
print('Processing', date, card)
|
||||
day = str(date.date())
|
||||
|
||||
if day not in days:
|
||||
days[day] = set()
|
||||
|
||||
days[day].add(card)
|
||||
|
||||
print(days)
|
||||
|
||||
for day, cards in days.items():
|
||||
print(day, len(cards))
|
||||
|
||||
models.StatsSpaceActivity.objects.update_or_create(
|
||||
date=day,
|
||||
defaults=dict(card_scans=len(cards)),
|
||||
)
|
||||
|
||||
print('Done.')
|
||||
|
21
apiserver/scripts/import_member_counts.py
Executable file
21
apiserver/scripts/import_member_counts.py
Executable file
@@ -0,0 +1,21 @@
|
||||
# Expects a old_counts.csv of the historical counts in format:
|
||||
# date,member_count,green_count
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
with open('old_counts.csv', newline='') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
print('Adding', row['date'], row['member_count'], row['green_count'])
|
||||
|
||||
models.StatsMemberCount.objects.update_or_create(
|
||||
date=row['date'],
|
||||
defaults=dict(member_count=row['member_count'], green_count=row['green_count']),
|
||||
)
|
||||
|
||||
print('Done.')
|
186
apiserver/scripts/import_missing_paypal.py
Executable file
186
apiserver/scripts/import_missing_paypal.py
Executable file
@@ -0,0 +1,186 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
from apiserver.api import models, old_models, utils
|
||||
|
||||
def find_name(t):
|
||||
try:
|
||||
p_info = t['payer_info']
|
||||
except KeyError:
|
||||
return 'Unknown Name'
|
||||
try:
|
||||
return p_info['payer_name']['given_name'] + ' ' + p_info['payer_name']['surname']
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
return t['shipping_info']['name']
|
||||
except KeyError:
|
||||
pass
|
||||
try:
|
||||
return p_info['payer_name']['alternate_full_name']
|
||||
except KeyError:
|
||||
return 'Unknown Name'
|
||||
|
||||
def build_tx(t):
|
||||
t_info = t['transaction_info']
|
||||
p_info = t['payer_info']
|
||||
amount = float(t_info['transaction_amount']['value'])
|
||||
return dict(
|
||||
account_type='PayPal',
|
||||
amount=amount,
|
||||
date=t_info['transaction_updated_date'].split('T')[0],
|
||||
info_source='PayPal IPN',
|
||||
payment_method='PayPal',
|
||||
paypal_payer_id=t_info['paypal_account_id'],
|
||||
paypal_txn_id=t_info['transaction_id'],
|
||||
reference_number=t_info['transaction_id'],
|
||||
memo=t_info.get('transaction_subject', 'no memo') + ' (import missing paypal script)',
|
||||
)
|
||||
|
||||
def create_unmatched_member_tx(t):
|
||||
t_info = t['transaction_info']
|
||||
p_info = t['payer_info']
|
||||
transactions = models.Transaction.objects
|
||||
|
||||
report_memo = 'Cant link sender name, {}, email: {}, note: {}'.format(
|
||||
find_name(t),
|
||||
p_info['email_address'],
|
||||
'(import missing paypal script)',
|
||||
)
|
||||
|
||||
return transactions.create(
|
||||
**build_tx(t),
|
||||
report_memo=report_memo,
|
||||
report_type='Unmatched Member',
|
||||
)
|
||||
|
||||
def create_member_dues_tx(t, member, num_months):
|
||||
transactions = models.Transaction.objects
|
||||
|
||||
# new member 3 for 2 will have to be manual anyway
|
||||
if num_months == 11:
|
||||
num_months = 12
|
||||
|
||||
user = getattr(member, 'user', None)
|
||||
|
||||
tx = transactions.create(
|
||||
**build_tx(t),
|
||||
member_id=member.id,
|
||||
number_of_membership_months=num_months,
|
||||
user=user,
|
||||
)
|
||||
utils.tally_membership_months(member)
|
||||
return tx
|
||||
|
||||
def create_unmatched_purchase_tx(t, member):
|
||||
t_info = t['transaction_info']
|
||||
p_info = t['payer_info']
|
||||
transactions = models.Transaction.objects
|
||||
|
||||
user = getattr(member, 'user', None)
|
||||
report_memo = 'Unknown payment reason, {}, email: {}, note: {}'.format(
|
||||
find_name(t),
|
||||
p_info['email_address'],
|
||||
'(import missing paypal script)',
|
||||
)
|
||||
|
||||
return transactions.create(
|
||||
**build_tx(t),
|
||||
member_id=member.id,
|
||||
report_memo=report_memo,
|
||||
report_type='Unmatched Purchase',
|
||||
user=user,
|
||||
)
|
||||
|
||||
|
||||
PAYPAL_FOLDER = 'missing_paypal/'
|
||||
|
||||
transactions = models.Transaction.objects.all()
|
||||
hints = models.PayPalHint.objects.all()
|
||||
members = models.Member.objects.all()
|
||||
|
||||
paypal_files = os.listdir(PAYPAL_FOLDER)
|
||||
paypal_json = [x for x in paypal_files if x.endswith('.json')]
|
||||
|
||||
if paypal_json:
|
||||
print('Found paypal json files:', paypal_json)
|
||||
else:
|
||||
print('Couldnt find any paypal json files in', PAYPAL_FOLDER)
|
||||
exit(1)
|
||||
|
||||
paypal_txs = []
|
||||
num_unmatched = 0
|
||||
num_dues = 0
|
||||
num_noreason = 0
|
||||
|
||||
for filename in paypal_json:
|
||||
with open(PAYPAL_FOLDER + filename) as f:
|
||||
j = json.load(f)
|
||||
paypal_txs.extend(j['transaction_details'])
|
||||
|
||||
print('Num transactions found:', len(paypal_txs))
|
||||
print('Importing transactions into portal...')
|
||||
|
||||
for t in paypal_txs:
|
||||
t_info = t['transaction_info']
|
||||
|
||||
account_id = t_info.get('paypal_account_id', None)
|
||||
if not account_id:
|
||||
print('Skipping tx id: {}, no payer (could be bank tx):'.format(
|
||||
t_info['transaction_id'],
|
||||
))
|
||||
print(t_info)
|
||||
print()
|
||||
continue
|
||||
|
||||
reference = t_info['transaction_id'][:11]
|
||||
|
||||
similar = transactions.filter(reference_number__startswith=reference)
|
||||
if similar.exists():
|
||||
tx = similar.first()
|
||||
print('Skipping tx id: {}, transaction already in portal:'.format(
|
||||
t_info['transaction_id'],
|
||||
))
|
||||
print('https://spaceport.dns.t0.vc/transactions/'+str(tx.id))
|
||||
print()
|
||||
continue
|
||||
|
||||
print('Inspecting tx id:', t_info['transaction_id'])
|
||||
|
||||
if not hints.filter(account=t_info['paypal_account_id']).exists():
|
||||
print('Unable to associate with member, reporting')
|
||||
create_unmatched_member_tx(t)
|
||||
num_unmatched += 1
|
||||
continue
|
||||
|
||||
amount = float(t_info['transaction_amount']['value'])
|
||||
|
||||
member_id = hints.get(account=t_info['paypal_account_id']).member_id
|
||||
member = members.get(id=member_id)
|
||||
print('Found member', member.first_name, member.last_name)
|
||||
monthly_fees = member.monthly_fees
|
||||
|
||||
if amount.is_integer() and monthly_fees and amount % monthly_fees == 0:
|
||||
num_months = int(amount // monthly_fees)
|
||||
else:
|
||||
num_months = 0
|
||||
|
||||
if num_months:
|
||||
print('Amount valid for membership dues, adding months:', num_months)
|
||||
create_member_dues_tx(t, member, num_months)
|
||||
num_dues += 1
|
||||
continue
|
||||
|
||||
print('Unable to find a reason for payment, reporting')
|
||||
create_unmatched_purchase_tx(t, member)
|
||||
num_noreason += 1
|
||||
|
||||
|
||||
print('Num unmatched members:', num_unmatched)
|
||||
print('Num member dues:', num_dues)
|
||||
print('Num no reason:', num_noreason)
|
||||
print('Num skipped:', len(paypal_txs) - num_unmatched - num_dues - num_noreason)
|
||||
print('Done.')
|
261
apiserver/scripts/import_old_portal.py
Executable file
261
apiserver/scripts/import_old_portal.py
Executable file
@@ -0,0 +1,261 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
from django.utils import timezone
|
||||
from apiserver.api import models, old_models, utils
|
||||
|
||||
MEMBER_FIELDS = [
|
||||
'id',
|
||||
# email -> old_email
|
||||
'first_name',
|
||||
'last_name',
|
||||
'preferred_name',
|
||||
'status',
|
||||
'phone',
|
||||
'expire_date',
|
||||
'current_start_date',
|
||||
'application_date',
|
||||
'vetted_date',
|
||||
'monthly_fees',
|
||||
'emergency_contact_name',
|
||||
'emergency_contact_phone',
|
||||
# minor -> is_minor
|
||||
'birthdate',
|
||||
'guardian_name',
|
||||
'street_address',
|
||||
# city, provice -> city
|
||||
'postal_code',
|
||||
]
|
||||
|
||||
TRANSACTION_FIELDS = [
|
||||
'id',
|
||||
'member_id',
|
||||
'date',
|
||||
'amount',
|
||||
'reference_number',
|
||||
'memo',
|
||||
'number_of_membership_months',
|
||||
'payment_method',
|
||||
'category',
|
||||
'account_type',
|
||||
'info_source',
|
||||
]
|
||||
|
||||
CARD_FIELDS = [
|
||||
'id',
|
||||
'member_id',
|
||||
'card_number',
|
||||
'notes',
|
||||
'last_seen_at',
|
||||
'active_status',
|
||||
]
|
||||
|
||||
COURSE_FIELDS = [
|
||||
'id',
|
||||
'name',
|
||||
'description',
|
||||
# True -> is_old
|
||||
]
|
||||
|
||||
SESSION_FIELDS = [
|
||||
'id',
|
||||
# course_id -> course
|
||||
# instructor -> old_instructor
|
||||
# datetime -> fix timezone
|
||||
'cost',
|
||||
]
|
||||
|
||||
TRAINING_FIELDS = [
|
||||
'id',
|
||||
# class_session_id -> session
|
||||
'member_id',
|
||||
# attendance_status -> capitalize
|
||||
'sign_up_date',
|
||||
'paid_date',
|
||||
]
|
||||
|
||||
photo_folders = os.listdir('old_photos')
|
||||
print('Found {} member photo folders'.format(len(photo_folders)))
|
||||
|
||||
|
||||
print('Deleting all members...')
|
||||
models.Member.objects.all().delete()
|
||||
print('Importing old members...')
|
||||
old = old_models.Members.objects.using('old_portal').all()
|
||||
|
||||
import_date = old.last().web_crawl_date.date()
|
||||
print('Using import date:', import_date)
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
if o.status == 'Contractor':
|
||||
print('Skipping contractor member #{} - {} {}'.format(
|
||||
o.id, o.first_name, o.last_name
|
||||
))
|
||||
continue
|
||||
|
||||
for f in MEMBER_FIELDS:
|
||||
new[f] = o.__dict__.get(f, None)
|
||||
|
||||
if o.city and o.province:
|
||||
new['city'] = '{}, {}'.format(o.city, o.province)
|
||||
new['old_email'] = o.email
|
||||
new['is_minor'] = o.minor
|
||||
new['paused_date'] = None
|
||||
|
||||
small, medium, large = None, None, None
|
||||
if str(o.id) in photo_folders:
|
||||
folder = 'old_photos/' + str(o.id)
|
||||
if 'photo.jpg' in os.listdir(folder):
|
||||
small, medium, large = utils.process_image_upload(folder + '/photo.jpg')
|
||||
print('Found a photo')
|
||||
|
||||
models.Member.objects.create(photo_small=small, photo_medium=medium, photo_large=large, **new)
|
||||
print('Imported member #{} - {} {}'.format(
|
||||
o.id, o.first_name, o.last_name
|
||||
))
|
||||
|
||||
|
||||
print('Deleting all transactions...')
|
||||
models.Transaction.objects.all().delete()
|
||||
print('Importing old transactions...')
|
||||
old = old_models.Transactions.objects.using('old_portal').all()
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
for f in TRANSACTION_FIELDS:
|
||||
tmp = o.__dict__.get(f, None)
|
||||
if isinstance(tmp, str):
|
||||
new[f] = tmp.replace('Paypal', 'PayPal')
|
||||
else:
|
||||
new[f] = tmp
|
||||
|
||||
models.Transaction.objects.create(**new)
|
||||
print('Imported transaction #{} - {} {}'.format(
|
||||
o.id, o.member_id, o.category
|
||||
))
|
||||
|
||||
print('Faking membership months...')
|
||||
members = models.Member.objects.all()
|
||||
bad_count = 0
|
||||
|
||||
for m in members:
|
||||
old_status = m.status
|
||||
old_expire = m.expire_date
|
||||
|
||||
if 'Former' in old_status:
|
||||
m.status = 'Old Portal ' + old_status
|
||||
m.save()
|
||||
continue
|
||||
if not m.current_start_date: continue
|
||||
|
||||
tx, _ = utils.fake_missing_membership_months(m)
|
||||
utils.tally_membership_months(m, import_date)
|
||||
utils.gen_member_forms(m)
|
||||
|
||||
if tx:
|
||||
print(m.first_name, m.last_name, tx.memo)
|
||||
|
||||
if old_status != m.status or old_expire != m.expire_date:
|
||||
print('Expire / status mismatch member:', m.__dict__)
|
||||
print('New status:', m.status)
|
||||
print('Old status:', old_status)
|
||||
print('New expire:', m.expire_date)
|
||||
print('Old expire:', old_expire)
|
||||
print('')
|
||||
bad_count += 1
|
||||
|
||||
print('Import mismatch count:', bad_count)
|
||||
|
||||
print('Pausing former members...')
|
||||
for m in members:
|
||||
if 'Former' in m.status:
|
||||
paused_date = m.expire_date or datetime.date.today()
|
||||
m.paused_date = paused_date
|
||||
m.save()
|
||||
print('Paused', m.first_name, m.last_name)
|
||||
|
||||
|
||||
|
||||
print('Deleting all cards...')
|
||||
models.Card.objects.all().delete()
|
||||
print('Importing old cards...')
|
||||
old = old_models.AccessKeys.objects.using('old_portal').all()
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
for f in CARD_FIELDS:
|
||||
new[f] = o.__dict__.get(f, None)
|
||||
|
||||
models.Card.objects.create(**new)
|
||||
print('Imported card #{} - {} {}'.format(
|
||||
o.id, o.card_number, o.notes
|
||||
))
|
||||
|
||||
|
||||
print('Deleting all courses...')
|
||||
models.Course.objects.all().delete()
|
||||
print('Importing old courses...')
|
||||
old = old_models.Courses.objects.using('old_portal').all()
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
for f in COURSE_FIELDS:
|
||||
new[f] = o.__dict__.get(f, None)
|
||||
new['name'] = new['name'].split('<',1)[0]
|
||||
new['is_old'] = True
|
||||
|
||||
models.Course.objects.create(**new)
|
||||
print('Imported course #{} - {}'.format(
|
||||
o.id, new['name']
|
||||
))
|
||||
|
||||
|
||||
print('Deleting all sessions...')
|
||||
models.Session.objects.all().delete()
|
||||
print('Importing old session...')
|
||||
old = old_models.ClassSessions.objects.using('old_portal').all()
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
for f in SESSION_FIELDS:
|
||||
new[f] = o.__dict__.get(f, None)
|
||||
new['course'] = models.Course.objects.get(id=o.course_id)
|
||||
new['old_instructor'] = o.instructor
|
||||
dt = o.datetime.replace(tzinfo=None)
|
||||
dt = timezone.pytz.timezone('America/Edmonton').localize(dt)
|
||||
new['datetime'] = dt.astimezone(timezone.pytz.UTC)
|
||||
|
||||
models.Session.objects.create(**new)
|
||||
print('Imported session #{} - {} {}'.format(
|
||||
o.id, o.instructor, new['course']
|
||||
))
|
||||
|
||||
|
||||
print('Deleting all training...')
|
||||
models.Training.objects.all().delete()
|
||||
print('Importing old training...')
|
||||
old = old_models.ClassRegistrants.objects.using('old_portal').all()
|
||||
|
||||
for o in old:
|
||||
new = {}
|
||||
|
||||
for f in TRAINING_FIELDS:
|
||||
new[f] = o.__dict__.get(f, None)
|
||||
new['session'] = models.Session.objects.get(id=o.class_session_id)
|
||||
new['attendance_status'] = o.attendance_status.capitalize()
|
||||
|
||||
models.Training.objects.create(**new)
|
||||
print('Imported training #{} - {} {}'.format(
|
||||
o.id, new['session'], o.member_id
|
||||
))
|
||||
|
||||
|
||||
print('Done.')
|
59
apiserver/scripts/import_rabbit_group.py
Executable file
59
apiserver/scripts/import_rabbit_group.py
Executable file
@@ -0,0 +1,59 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
from apiserver.api import models, utils
|
||||
|
||||
def clean(name):
|
||||
return re.sub(r'[^a-z]', '', name.lower())
|
||||
|
||||
with open('ad-rabbit.json', 'r') as f:
|
||||
ad_dirty = json.load(f)
|
||||
|
||||
with open('ad-dump.json', 'r') as f:
|
||||
ad_dump = json.load(f)
|
||||
|
||||
ad = {}
|
||||
for sam in ad_dirty:
|
||||
try:
|
||||
ad[clean(sam)] = ad_dump[sam]['mail']
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
members = models.Member.objects.all()
|
||||
|
||||
portal = {}
|
||||
for m in members:
|
||||
name = m.first_name + m.last_name
|
||||
portal[clean(name)] = m
|
||||
|
||||
good_members = {}
|
||||
|
||||
for ad_name, email in ad.items():
|
||||
if ad_name in portal:
|
||||
good_members[ad_name] = portal[ad_name]
|
||||
print('found ad name match', ad_name)
|
||||
else:
|
||||
print('cant find ad name', ad_name)
|
||||
print('searching for email...')
|
||||
for m in members:
|
||||
if m.old_email and m.old_email.lower() == email.lower():
|
||||
good_members[ad_name] = m
|
||||
print(' found email', email)
|
||||
break
|
||||
else:
|
||||
print(' cant link email', email)
|
||||
|
||||
print()
|
||||
print()
|
||||
|
||||
for m in good_members.values():
|
||||
if not m.rabbit_cert_date:
|
||||
m.rabbit_cert_date = utils.today_alberta_tz()
|
||||
print('certified', m.first_name, m.last_name)
|
||||
m.save()
|
||||
else:
|
||||
print('skipping', m.first_name, m.last_name)
|
22
apiserver/scripts/import_signup_counts.py
Executable file
22
apiserver/scripts/import_signup_counts.py
Executable file
@@ -0,0 +1,22 @@
|
||||
# Expects a old_counts.csv of the historical counts in format:
|
||||
# month,signup_count
|
||||
# month in YYYY-MM format
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
with open('old_counts.csv', newline='') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
print('Adding', row['month'], row['signup_count'])
|
||||
|
||||
models.StatsSignupCount.objects.update_or_create(
|
||||
month=row['month']+'-01',
|
||||
defaults=dict(signup_count=row['signup_count']),
|
||||
)
|
||||
|
||||
print('Done.')
|
21
apiserver/scripts/import_six_month_plus_count.py
Executable file
21
apiserver/scripts/import_six_month_plus_count.py
Executable file
@@ -0,0 +1,21 @@
|
||||
# Expects a old_counts.csv of the historical counts in format:
|
||||
# date,six_month_plus_count
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
with open('old_counts.csv', newline='') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
print('Adding', row['date'], row['six_month_plus_count'])
|
||||
|
||||
models.StatsMemberCount.objects.update_or_create(
|
||||
date=row['date'],
|
||||
defaults=dict(six_month_plus_count=row['six_month_plus_count']),
|
||||
)
|
||||
|
||||
print('Done.')
|
59
apiserver/scripts/import_trotec_group.py
Executable file
59
apiserver/scripts/import_trotec_group.py
Executable file
@@ -0,0 +1,59 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
import re
|
||||
from apiserver.api import models, utils
|
||||
|
||||
def clean(name):
|
||||
return re.sub(r'[^a-z]', '', name.lower())
|
||||
|
||||
with open('ad-trotec.json', 'r') as f:
|
||||
ad_dirty = json.load(f)
|
||||
|
||||
with open('ad-dump.json', 'r') as f:
|
||||
ad_dump = json.load(f)
|
||||
|
||||
ad = {}
|
||||
for sam in ad_dirty:
|
||||
try:
|
||||
ad[clean(sam)] = ad_dump[sam]['mail']
|
||||
except KeyError:
|
||||
continue
|
||||
|
||||
members = models.Member.objects.all()
|
||||
|
||||
portal = {}
|
||||
for m in members:
|
||||
name = m.first_name + m.last_name
|
||||
portal[clean(name)] = m
|
||||
|
||||
good_members = {}
|
||||
|
||||
for ad_name, email in ad.items():
|
||||
if ad_name in portal:
|
||||
good_members[ad_name] = portal[ad_name]
|
||||
print('found ad name match', ad_name)
|
||||
else:
|
||||
print('cant find ad name', ad_name)
|
||||
print('searching for email...')
|
||||
for m in members:
|
||||
if m.old_email and m.old_email.lower() == email.lower():
|
||||
good_members[ad_name] = m
|
||||
print(' found email', email)
|
||||
break
|
||||
else:
|
||||
print(' cant link email', email)
|
||||
|
||||
print()
|
||||
print()
|
||||
|
||||
for m in good_members.values():
|
||||
if not m.trotec_cert_date:
|
||||
m.trotec_cert_date = utils.today_alberta_tz()
|
||||
print('certified', m.first_name, m.last_name)
|
||||
m.save()
|
||||
else:
|
||||
print('skipping', m.first_name, m.last_name)
|
21
apiserver/scripts/import_vetted_count.py
Executable file
21
apiserver/scripts/import_vetted_count.py
Executable file
@@ -0,0 +1,21 @@
|
||||
# Expects a old_counts.csv of the historical counts in format:
|
||||
# date,vetted_count
|
||||
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import csv
|
||||
from apiserver.api import models
|
||||
|
||||
with open('old_counts.csv', newline='') as csvfile:
|
||||
reader = csv.DictReader(csvfile)
|
||||
for row in reader:
|
||||
print('Adding', row['date'], row['vetted_count'])
|
||||
|
||||
models.StatsMemberCount.objects.update_or_create(
|
||||
date=row['date'],
|
||||
defaults=dict(vetted_count=row['vetted_count']),
|
||||
)
|
||||
|
||||
print('Done.')
|
98
apiserver/scripts/lockout_auth_update.py
Executable file
98
apiserver/scripts/lockout_auth_update.py
Executable file
@@ -0,0 +1,98 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
from django.utils.timezone import now, pytz
|
||||
from apiserver.api import models, utils
|
||||
|
||||
# Member orientation
|
||||
print('Updating member orientation dates')
|
||||
sessions = models.Session.objects.filter(course = 249)
|
||||
|
||||
def get_member(obj):
|
||||
# same as in serialzers.py -> get_cards for example
|
||||
if obj.user:
|
||||
member = obj.user.member
|
||||
else:
|
||||
member = models.Member.objects.get(id=obj.member_id)
|
||||
return member
|
||||
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.orientation_date:
|
||||
member.orientation_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
# Lathe
|
||||
print('Updating lathe training dates')
|
||||
sessions = models.Session.objects.filter(course = 281)
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.lathe_cert_date:
|
||||
member.lathe_cert_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
# Manual Mill
|
||||
print('Updating mill training dates')
|
||||
sessions = models.Session.objects.filter(course = 283)
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.mill_cert_date:
|
||||
member.mill_cert_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
|
||||
# Woodworking tools
|
||||
print('Updating woodworking training dates')
|
||||
sessions = models.Session.objects.filter(course = 261)
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.wood_cert_date:
|
||||
member.wood_cert_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
# Woodworking-2 tools
|
||||
print('Updating woodworking-2 training dates')
|
||||
sessions = models.Session.objects.filter(course = 401)
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.wood2_cert_date:
|
||||
member.wood2_cert_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
# CNC tools
|
||||
print('Updating CNC training dates')
|
||||
sessions = models.Session.objects.filter(course = 259)
|
||||
|
||||
for session in sessions:
|
||||
students = models.Training.objects.filter(session = session)
|
||||
for student in students:
|
||||
if student.attendance_status == 'Attended':
|
||||
member = get_member(student)
|
||||
if not member.cnc_cert_date:
|
||||
member.cnc_cert_date = session.datetime.astimezone(pytz.timezone('America/Edmonton')).date()
|
||||
member.save()
|
||||
|
||||
print('Done.')
|
17
apiserver/scripts/sync_member_statuses.py
Executable file
17
apiserver/scripts/sync_member_statuses.py
Executable file
@@ -0,0 +1,17 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
from apiserver.api import models
|
||||
|
||||
members = models.Member.objects.all()
|
||||
count = 0
|
||||
|
||||
for m in members:
|
||||
if m.paused_date and m.status in ['Prepaid', 'Current', 'Due', 'Overdue']:
|
||||
print('Setting', m.first_name, m.last_name, 'to Former Member.')
|
||||
m.status = 'Former Member'
|
||||
count += 1
|
||||
m.save()
|
||||
|
||||
print('Processed', count)
|
91
apiserver/scripts/train_paypal_ids.py
Executable file
91
apiserver/scripts/train_paypal_ids.py
Executable file
@@ -0,0 +1,91 @@
|
||||
import django, sys, os
|
||||
os.environ['DJANGO_SETTINGS_MODULE'] = 'apiserver.settings'
|
||||
django.setup()
|
||||
|
||||
import datetime
|
||||
import json
|
||||
from apiserver.api import models, old_models, utils
|
||||
|
||||
PAYPAL_FOLDER = 'old_paypal/'
|
||||
transactions = models.Transaction.objects.all()
|
||||
|
||||
paypal_files = os.listdir(PAYPAL_FOLDER)
|
||||
paypal_json = [x for x in paypal_files if x.endswith('.json')]
|
||||
|
||||
if paypal_json:
|
||||
print('Found paypal json files:', paypal_json)
|
||||
else:
|
||||
print('Couldnt find any paypal json files in', PAYPAL_FOLDER)
|
||||
exit(1)
|
||||
|
||||
paypal_txs = []
|
||||
|
||||
for filename in paypal_json:
|
||||
with open(PAYPAL_FOLDER + filename) as f:
|
||||
j = json.load(f)
|
||||
paypal_txs.extend(j['transaction_details'])
|
||||
|
||||
print('Num transactions found:', len(paypal_txs))
|
||||
print('Linking with portal transactions...')
|
||||
|
||||
paypal_accounts = {}
|
||||
|
||||
for t in paypal_txs:
|
||||
t_info = t['transaction_info']
|
||||
|
||||
|
||||
account_id = t_info.get('paypal_account_id', None)
|
||||
if not account_id:
|
||||
print('Skipping tx id: {}, no payer (could be bank tx)'.format(
|
||||
t_info['transaction_id'],
|
||||
))
|
||||
continue
|
||||
|
||||
if account_id not in paypal_accounts:
|
||||
paypal_accounts[account_id] = []
|
||||
|
||||
|
||||
reference = t_info['transaction_id'][:11]
|
||||
try:
|
||||
portal_tx = transactions.get(reference_number=reference)
|
||||
paypal_accounts[account_id].append(portal_tx.member_id)
|
||||
except models.Transaction.DoesNotExist:
|
||||
print('Unable to find portal transaction for id: {}, ref: {}, date: {}, name: {} {}, email: {}'.format(
|
||||
t_info['transaction_id'],
|
||||
reference,
|
||||
t_info['transaction_initiation_date'][:10],
|
||||
t['payer_info']['payer_name'].get('given_name', 'unknown'),
|
||||
t['payer_info']['payer_name'].get('surname', 'unknown'),
|
||||
t['payer_info'].get('email_address', 'unknown'),
|
||||
))
|
||||
|
||||
print('Num paypal accounts found:', len(paypal_accounts))
|
||||
print('Linking with portal members...')
|
||||
count = 0
|
||||
|
||||
for account_id, member_ids in paypal_accounts.items():
|
||||
if len(member_ids) == 0:
|
||||
print('Skipping account {}, no members found'.format(
|
||||
account_id,
|
||||
))
|
||||
continue
|
||||
|
||||
member_id = member_ids[0]
|
||||
|
||||
if len(set(member_ids)) > 1:
|
||||
print('Account {} has multiple members {}, assuming {}'.format(
|
||||
account_id,
|
||||
str(set(member_ids)),
|
||||
member_id,
|
||||
))
|
||||
|
||||
print(account_id, '-->', member_id)
|
||||
|
||||
models.PayPalHint.objects.update_or_create(
|
||||
account=account_id,
|
||||
defaults=dict(member_id=member_id),
|
||||
)
|
||||
count += 1
|
||||
|
||||
print('Num paypal hints processed:', count)
|
||||
print('Done.')
|
Reference in New Issue
Block a user