33"""
44
55from secrets import token_hex
6+ from datetime import datetime , time , timedelta
7+ import csv
8+ import click
69
710from . import app , db
8- from .models import Freshman , Packet , UpperSignature
11+ from .models import Freshman , Packet , UpperSignature , FreshSignature
12+ from .ldap import ldap_get_eboard , ldap_get_live_onfloor
913
1014@app .cli .command ("create-secret" )
1115def create_secret ():
@@ -15,22 +19,108 @@ def create_secret():
1519 print ("Here's your random secure token:" )
1620 print (token_hex ())
1721
18- @app .cli .command ("create-packet" )
19- def create_packet ():
22+ class CSVFreshman :
23+ def __init__ (self , row ):
24+ self .name = row [0 ]
25+ self .rit_username = row [3 ]
26+ self .onfloor = row [1 ] == "TRUE"
27+
28+ def parse_csv (freshmen_csv ):
29+ print ("Parsing file..." )
30+ try :
31+ with open (freshmen_csv , newline = '' ) as freshmen_csv_file :
32+ return {freshman .rit_username : freshman for freshman in map (CSVFreshman , csv .reader (freshmen_csv_file ))}
33+ except Exception as e :
34+ print ("Failure while parsing CSV" )
35+ raise e
36+
37+ @app .cli .command ("sync-freshmen" )
38+ @click .argument ("freshmen_csv" )
39+ def sync_freshmen (freshmen_csv ):
2040 """
21- Example/test code for adding a new packet to the database .
41+ Updates the freshmen entries in the DB to match the given CSV .
2242 """
23- print ("Generating new rows..." )
43+ freshmen_in_csv = parse_csv (freshmen_csv )
44+
45+ print ("Syncing contents with the DB..." )
46+ freshmen_in_db = {freshman .rit_username : freshman for freshman in Freshman .query .all ()}
2447
25- freshman = Freshman (rit_username = "bob1234" , name = "Bob Freshy" , onfloor = True )
26- db .session .add (freshman )
48+ for csv_freshman in freshmen_in_csv .values ():
49+ if csv_freshman .rit_username not in freshmen_in_db :
50+ # This is a new freshman so add them to the DB
51+ freshmen_in_db [csv_freshman .rit_username ] = Freshman (rit_username = csv_freshman .rit_username ,
52+ name = csv_freshman .name , onfloor = csv_freshman .onfloor )
53+ db .session .add (freshmen_in_db [csv_freshman .rit_username ])
54+ else :
55+ # This freshman is already in the DB so just update them
56+ freshmen_in_db [csv_freshman .rit_username ].onfloor = csv_freshman .onfloor
57+ freshmen_in_db [csv_freshman .rit_username ].name = csv_freshman .name
2758
28- packet = Packet (freshman = freshman )
29- db .session .add (packet )
59+ # Update all freshmen entries that represent people who are no longer freshmen
60+ for freshman in filter (lambda freshman : freshman .rit_username not in freshmen_in_csv , freshmen_in_db .values ()):
61+ freshman .onfloor = False
3062
31- db .session .add (UpperSignature (packet = packet , member = "somehuman" ))
32- db .session .add (UpperSignature (packet = packet , member = "reeehuman" , eboard = True ))
63+ # Update the freshmen signatures of each open or future packet
64+ for packet in Packet .query .filter (Packet .end > datetime .now ()).all ():
65+ # Handle the freshmen that are no longer onfloor
66+ for fresh_sig in filter (lambda fresh_sig : not fresh_sig .freshman .onfloor , packet .fresh_signatures ):
67+ FreshSignature .query .filter_by (packet_id = fresh_sig .packet_id ,
68+ freshman_username = fresh_sig .freshman_username ).delete ()
69+
70+ # Add any new onfloor freshmen
71+ # pylint: disable=cell-var-from-loop
72+ current_fresh_sigs = set (map (lambda fresh_sig : fresh_sig .freshman_username , packet .fresh_signatures ))
73+ for csv_freshman in filter (lambda csv_freshman : csv_freshman .rit_username not in current_fresh_sigs ,
74+ freshmen_in_csv .values ()):
75+ db .session .add (FreshSignature (packet = packet , freshman = freshmen_in_db [csv_freshman .rit_username ]))
3376
3477 db .session .commit ()
78+ print ("Done!" )
79+
80+ @app .cli .command ("create-packets" )
81+ @click .argument ("freshmen_csv" )
82+ def create_packets (freshmen_csv ):
83+ """
84+ Creates a new packet season for each of the freshmen in the given CSV.
85+ """
86+ print ("WARNING: The 'sync-freshmen' command must be run first to ensure that the state of floor is up to date." )
87+ if input ("Continue? (y/N): " ).lower () != "y" :
88+ return
89+
90+ # Collect the necessary data
91+ base_date = None
92+ while base_date is None :
93+ try :
94+ date_str = input ("Input the first day of packet season (format: MM/DD/YYYY): " )
95+ base_date = datetime .strptime (date_str , "%m/%d/%Y" ).date ()
96+ except ValueError :
97+ pass
3598
99+ start = datetime .combine (base_date , time (hour = 19 ))
100+ end = datetime .combine (base_date , time (hour = 23 , minute = 59 )) + timedelta (days = 14 )
101+
102+ print ("Fetching data from LDAP..." )
103+ eboard = [member .uid for member in ldap_get_eboard ()]
104+ onfloor = [member .uid for member in ldap_get_live_onfloor ()]
105+
106+ freshmen_in_csv = parse_csv (freshmen_csv )
107+
108+ # Create the new packets and the signatures
109+ print ("Creating DB entries..." )
110+ for freshman in freshmen_in_csv .values ():
111+ packet = Packet (freshman = Freshman .query .filter_by (rit_username = freshman .rit_username ).first (), start = start ,
112+ end = end )
113+ db .session .add (packet )
114+
115+ for username in eboard :
116+ db .session .add (UpperSignature (packet = packet , member = username , eboard = True ))
117+
118+ for username in onfloor :
119+ db .session .add (UpperSignature (packet = packet , member = username ))
120+
121+ for onfloor_freshman in Freshman .query .filter_by (onfloor = True ).filter (Freshman .rit_username !=
122+ freshman .rit_username ).all ():
123+ db .session .add (FreshSignature (packet = packet , freshman = onfloor_freshman ))
124+
125+ db .session .commit ()
36126 print ("Done!" )
0 commit comments