Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 13 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,19 @@ This will run the asset pipeline, start the Python server, and start BrowserSync

To add new dependencies, add them to `requirements.in` and then run `pip-compile requirements.in` to produce a new locked `requirements.txt`. Do not edit `requirements.txt` directly as it will be overwritten by future PRs.

after app initialization
### Local database

You can run the database locally using the docker compose, make sure to upgrade it as explained below

To populate it with dev data for example, you can use the command

```
PGPASSWORD='[DB PASSWORD]' pg_dump -h postgres.csh.rit.edu -p 5432 -U conditional-dev conditional-dev | PGPASSWORD='fancypantspassword' psql -h localhost -p 5432 -U conditional conditional
```

This can be helpful for changing the database schema

NOTE: to use flask db commands with a database running in the compose file, you will have to update your url to point to localhost, not conditional-postgres

### Database Migrations

Expand Down
9 changes: 5 additions & 4 deletions conditional/blueprints/member_management.py
Original file line number Diff line number Diff line change
Expand Up @@ -462,22 +462,20 @@ def member_management_upgrade_user(user_dict=None):
db.session.add(new_acct)
for fca in FreshmanCommitteeAttendance.query.filter(FreshmanCommitteeAttendance.fid == fid):
db.session.add(MemberCommitteeAttendance(uid, fca.meeting_id))
db.session.delete(fca)

for fts in FreshmanSeminarAttendance.query.filter(FreshmanSeminarAttendance.fid == fid):
db.session.add(MemberSeminarAttendance(uid, fts.seminar_id))
db.session.delete(fts)

for fhm in FreshmanHouseMeetingAttendance.query.filter(FreshmanHouseMeetingAttendance.fid == fid):
# Don't duplicate HM attendance records
mhm = MemberHouseMeetingAttendance.query.filter(
MemberHouseMeetingAttendance.meeting_id == fhm.meeting_id).first()
MemberHouseMeetingAttendance.meeting_id == fhm.meeting_id,
MemberHouseMeetingAttendance.uid == uid).first()
if mhm is None:
db.session.add(MemberHouseMeetingAttendance(
uid, fhm.meeting_id, fhm.excuse, fhm.attendance_status))
else:
log.info(f'Duplicate house meeting attendance! fid: {fid}, uid: {uid}, id: {fhm.meeting_id}')
db.session.delete(fhm)

new_account = ldap_get_member(uid)
if acct.onfloor_status:
Expand All @@ -487,6 +485,9 @@ def member_management_upgrade_user(user_dict=None):
if acct.room_number:
ldap_set_roomnumber(new_account, acct.room_number)

db.session.flush()
db.session.commit()

db.session.delete(acct)

db.session.flush()
Expand Down
6 changes: 3 additions & 3 deletions conditional/models/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ def __init__(self, uid, meeting_id):
class FreshmanCommitteeAttendance(db.Model):
__tablename__ = 'freshman_committee_attendance'
id = Column(Integer, primary_key=True)
fid = Column(ForeignKey('freshman_accounts.id'), nullable=False)
fid = Column(ForeignKey('freshman_accounts.id', ondelete="cascade"), nullable=False)
meeting_id = Column(ForeignKey('committee_meetings.id'), nullable=False)

def __init__(self, fid, meeting_id):
Expand Down Expand Up @@ -120,7 +120,7 @@ def __init__(self, uid, seminar_id):
class FreshmanSeminarAttendance(db.Model):
__tablename__ = 'freshman_seminar_attendance'
id = Column(Integer, primary_key=True)
fid = Column(ForeignKey('freshman_accounts.id'), nullable=False)
fid = Column(ForeignKey('freshman_accounts.id', ondelete="cascade"), nullable=False)
seminar_id = Column(ForeignKey('technical_seminars.id'), nullable=False)

def __init__(self, fid, seminar_id):
Expand Down Expand Up @@ -178,7 +178,7 @@ def __init__(self, uid, meeting_id, excuse, status):
class FreshmanHouseMeetingAttendance(db.Model):
__tablename__ = 'freshman_hm_attendance'
id = Column(Integer, primary_key=True)
fid = Column(ForeignKey('freshman_accounts.id'), nullable=False)
fid = Column(ForeignKey('freshman_accounts.id', ondelete="cascade"), nullable=False)
meeting_id = Column(ForeignKey('house_meetings.id'), nullable=False)
excuse = Column(Text)
attendance_status = Column(attendance_enum)
Expand Down
6 changes: 3 additions & 3 deletions conditional/util/member.py
Original file line number Diff line number Diff line change
Expand Up @@ -186,13 +186,13 @@ def get_voting_members():
active_not_intro = active_members - intro_members
active_not_intro = set(map(lambda member: member.uid, active_not_intro))

elligible_members = (active_not_intro - coop_members) | passed_fall_members
eligible_members = (active_not_intro - coop_members) | passed_fall_members

# Check to see if there's an Intro Evals in the future of this semester. If there is, everyone gets to vote!
before_evals_one = len(FreshmanAccount.query.filter(FreshmanAccount.eval_date > today).limit(1).all())
before_evals_two = len(FreshmanEvalData.query.filter(FreshmanEvalData.eval_date > today).limit(1).all())
if before_evals_one > 0 or before_evals_two > 0:
return elligible_members
return eligible_members

passing_dm = set(member.uid for member in MemberCommitteeAttendance.query.join(
CommitteeMeeting,
Expand Down Expand Up @@ -245,7 +245,7 @@ def get_voting_members():

passing_reqs = (passing_dm & passing_ts) - absent_hm

return elligible_members & passing_reqs
return eligible_members & passing_reqs


def gatekeep_status(username):
Expand Down
2 changes: 1 addition & 1 deletion config.env.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
PROFILING = env.get("CONDITIONAL_PROFILING", "false").lower() == "true"

# DB Info
SQLALCHEMY_DATABASE_URI = env.get("SQLALCHEMY_DATABASE_URI", "")
SQLALCHEMY_DATABASE_URI = "postgresql://conditional:fancypantspassword@conditional-postgres:5432/conditional"
SQLALCHEMY_TRACK_MODIFICATIONS = False

# LDAP config
Expand Down
24 changes: 24 additions & 0 deletions docker-compose.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
version: "3"
services:
conditional:
build: .
container_name: conditional
depends_on:
- conditional-postgres
ports:
- "127.0.0.1:8080:8080"
conditional-postgres:
image: docker.io/postgres
container_name: conditional-postgres
environment:
POSTGRES_PASSWORD: fancypantspassword
POSTGRES_USER: conditional
POSTGRES_DATABASE: conditional
ports:
- "127.0.0.1:5432:5432"
volumes:
- pgdata:/var/lib/postgresql

volumes:
pgdata:

36 changes: 36 additions & 0 deletions migrations/versions/7a3904cac24b_freshmen_data_cascade.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
"""Freshmen data cascade

Revision ID: 7a3904cac24b
Revises: e38beaf3e875
Create Date: 2026-02-03 12:14:37.119352

"""

# revision identifiers, used by Alembic.
revision = '7a3904cac24b'
down_revision = 'e38beaf3e875'

from alembic import op
import sqlalchemy as sa


def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint('freshman_committee_attendance_fid_fkey', 'freshman_committee_attendance', type_='foreignkey')
op.create_foreign_key(None, 'freshman_committee_attendance', 'freshman_accounts', ['fid'], ['id'], ondelete='cascade')
op.drop_constraint('freshman_hm_attendance_fid_fkey', 'freshman_hm_attendance', type_='foreignkey')
op.create_foreign_key(None, 'freshman_hm_attendance', 'freshman_accounts', ['fid'], ['id'], ondelete='cascade')
op.drop_constraint('freshman_seminar_attendance_fid_fkey', 'freshman_seminar_attendance', type_='foreignkey')
op.create_foreign_key(None, 'freshman_seminar_attendance', 'freshman_accounts', ['fid'], ['id'], ondelete='cascade')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_constraint(None, 'freshman_seminar_attendance', type_='foreignkey')
op.create_foreign_key('freshman_seminar_attendance_fid_fkey', 'freshman_seminar_attendance', 'freshman_accounts', ['fid'], ['id'])
op.drop_constraint(None, 'freshman_hm_attendance', type_='foreignkey')
op.create_foreign_key('freshman_hm_attendance_fid_fkey', 'freshman_hm_attendance', 'freshman_accounts', ['fid'], ['id'])
op.drop_constraint(None, 'freshman_committee_attendance', type_='foreignkey')
op.create_foreign_key('freshman_committee_attendance_fid_fkey', 'freshman_committee_attendance', 'freshman_accounts', ['fid'], ['id'])
# ### end Alembic commands ###
111 changes: 111 additions & 0 deletions migrations/versions/e38beaf3e875_update_db.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
"""update db

Revision ID: e38beaf3e875
Revises: 757e18146d16
Create Date: 2026-02-03 12:12:11.451367

"""

# revision identifiers, used by Alembic.
revision = 'e38beaf3e875'
down_revision = '757e18146d16'

from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql

def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_index('member_batch_users_id_idx', table_name='member_batch_users')
op.drop_table('member_batch_users')
op.drop_index('freshman_batch_pulls_id_idx', table_name='freshman_batch_pulls')
op.drop_table('freshman_batch_pulls')
op.drop_index('member_batch_pulls_id_idx', table_name='member_batch_pulls')
op.drop_table('member_batch_pulls')
op.drop_index('freshman_batch_users_id_pkey', table_name='freshman_batch_users')
op.drop_table('freshman_batch_users')
op.drop_table('batch_conditions')
op.alter_column('freshman_accounts', 'onfloor_status',
existing_type=sa.BOOLEAN(),
nullable=True)
op.alter_column('freshman_accounts', 'rit_username',
existing_type=sa.VARCHAR(length=10),
nullable=True)
op.alter_column('freshman_hm_attendance', 'attendance_status',
existing_type=postgresql.ENUM('Attended', 'Excused', 'Absent', name='attendance_enum'),
nullable=True)
op.alter_column('member_hm_attendance', 'attendance_status',
existing_type=postgresql.ENUM('Attended', 'Excused', 'Absent', name='attendance_enum'),
nullable=True)
op.drop_table('batch')
# ### end Alembic commands ###


def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.alter_column('member_hm_attendance', 'attendance_status',
existing_type=postgresql.ENUM('Attended', 'Excused', 'Absent', name='attendance_enum'),
nullable=False)
op.alter_column('freshman_hm_attendance', 'attendance_status',
existing_type=postgresql.ENUM('Attended', 'Excused', 'Absent', name='attendance_enum'),
nullable=False)
op.alter_column('freshman_accounts', 'rit_username',
existing_type=sa.VARCHAR(length=10),
nullable=False)
op.alter_column('freshman_accounts', 'onfloor_status',
existing_type=sa.BOOLEAN(),
nullable=False)
op.create_table('batch_conditions',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('value', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('condition', postgresql.ENUM('packet', 'seminar', 'committee', 'house', name='batch_ctype_enum'), autoincrement=False, nullable=False),
sa.Column('comparison', postgresql.ENUM('less', 'equal', 'greater', name='batch_comparison'), autoincrement=False, nullable=False),
sa.Column('batch_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['batch_id'], ['batch.id'], name='batch_conditions_fk'),
sa.PrimaryKeyConstraint('id', name='batch_conditions_pkey')
)
op.create_table('freshman_batch_users',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('fid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('batch_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['batch_id'], ['batch.id'], name='freshman_batch_users_fk'),
sa.ForeignKeyConstraint(['fid'], ['freshman_accounts.id'], name='freshman_batch_users_fk_1'),
sa.PrimaryKeyConstraint('id', name='freshman_batch_users_pkey')
)
op.create_index('freshman_batch_users_id_pkey', 'freshman_batch_users', ['id'], unique=True)
op.create_table('batch',
sa.Column('id', sa.INTEGER(), server_default=sa.text("nextval('batch_id_seq'::regclass)"), autoincrement=True, nullable=False),
sa.Column('name', sa.TEXT(), autoincrement=False, nullable=False),
sa.Column('uid', sa.VARCHAR(length=32), autoincrement=False, nullable=False),
sa.Column('approved', sa.BOOLEAN(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint('id', name='batch_pkey'),
postgresql_ignore_search_path=False
)
op.create_table('member_batch_pulls',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('uid', sa.VARCHAR(length=32), autoincrement=False, nullable=False),
sa.Column('approved', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=False),
sa.Column('reason', sa.TEXT(), server_default=sa.text("''::text"), autoincrement=False, nullable=False),
sa.Column('puller', sa.VARCHAR(), autoincrement=False, nullable=False),
sa.PrimaryKeyConstraint('id', name='member_batch_pulls_pkey')
)
op.create_index('member_batch_pulls_id_idx', 'member_batch_pulls', ['id'], unique=True)
op.create_table('freshman_batch_pulls',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('fid', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('approved', sa.BOOLEAN(), server_default=sa.text('false'), autoincrement=False, nullable=False),
sa.Column('reason', sa.TEXT(), server_default=sa.text("''::text"), autoincrement=False, nullable=False),
sa.Column('puller', sa.VARCHAR(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['fid'], ['freshman_accounts.id'], name='freshman_batch_pulls_fk_1'),
sa.PrimaryKeyConstraint('id', name='freshman_batch_pulls_pkey')
)
op.create_index('freshman_batch_pulls_id_idx', 'freshman_batch_pulls', ['id'], unique=True)
op.create_table('member_batch_users',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('uid', sa.VARCHAR(length=32), autoincrement=False, nullable=False),
sa.Column('batch_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.ForeignKeyConstraint(['batch_id'], ['batch.id'], name='member_batch_users_fk'),
sa.PrimaryKeyConstraint('id', name='member_batch_users_pkey')
)
op.create_index('member_batch_users_id_idx', 'member_batch_users', ['id'], unique=False)
# ### end Alembic commands ###