diff --git a/alembic/versions/9b657ae4c4ac_add_mivs_to_attendee_relationship.py b/alembic/versions/9b657ae4c4ac_add_mivs_to_attendee_relationship.py new file mode 100644 index 000000000..01e64a9dc --- /dev/null +++ b/alembic/versions/9b657ae4c4ac_add_mivs_to_attendee_relationship.py @@ -0,0 +1,63 @@ +"""Add MIVS to attendee relationship + +Revision ID: 9b657ae4c4ac +Revises: 318d761a5c62 +Create Date: 2024-10-07 20:53:07.005134 + +""" + + +# revision identifiers, used by Alembic. +revision = '9b657ae4c4ac' +down_revision = '318d761a5c62' +branch_labels = None +depends_on = None + +from alembic import op +import sqlalchemy as sa +import residue + + +try: + is_sqlite = op.get_context().dialect.name == 'sqlite' +except Exception: + is_sqlite = False + +if is_sqlite: + op.get_context().connection.execute('PRAGMA foreign_keys=ON;') + utcnow_server_default = "(datetime('now', 'utc'))" +else: + utcnow_server_default = "timezone('utc', current_timestamp)" + +def sqlite_column_reflect_listener(inspector, table, column_info): + """Adds parenthesis around SQLite datetime defaults for utcnow.""" + if column_info['default'] == "datetime('now', 'utc')": + column_info['default'] = utcnow_server_default + +sqlite_reflect_kwargs = { + 'listeners': [('column_reflect', sqlite_column_reflect_listener)] +} + +# =========================================================================== +# HOWTO: Handle alter statements in SQLite +# +# def upgrade(): +# if is_sqlite: +# with op.batch_alter_table('table_name', reflect_kwargs=sqlite_reflect_kwargs) as batch_op: +# batch_op.alter_column('column_name', type_=sa.Unicode(), server_default='', nullable=False) +# else: +# op.alter_column('table_name', 'column_name', type_=sa.Unicode(), server_default='', nullable=False) +# +# =========================================================================== + + +def upgrade(): + op.add_column('indie_developer', sa.Column('attendee_id', residue.UUID(), nullable=True)) + op.create_unique_constraint(op.f('uq_indie_developer_attendee_id'), 'indie_developer', ['attendee_id']) + op.create_foreign_key(op.f('fk_indie_developer_attendee_id_attendee'), 'indie_developer', 'attendee', ['attendee_id'], ['id']) + + +def downgrade(): + op.drop_constraint(op.f('fk_indie_developer_attendee_id_attendee'), 'indie_developer', type_='foreignkey') + op.drop_constraint(op.f('uq_indie_developer_attendee_id'), 'indie_developer', type_='unique') + op.drop_column('indie_developer', 'attendee_id') diff --git a/celerybeat-schedule b/celerybeat-schedule index 0fd001d91..2b81de8c9 100644 Binary files a/celerybeat-schedule and b/celerybeat-schedule differ diff --git a/docker-compose.yml b/docker-compose.yml index c069f896e..d72f3cc4f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -18,7 +18,6 @@ x-uber: &uber - uber_secret_broker_url=amqp://celery:celery@rabbitmq:5672/uber - uber_hostname=localhost - uber_dev_box=True - - UBER_CONFIG_FILES=uber.ini - LOG_CONFIG=true volumes: - .:/app/ diff --git a/uber/configspec.ini b/uber/configspec.ini index 9d309bdcc..6a873b4cd 100644 --- a/uber/configspec.ini +++ b/uber/configspec.ini @@ -1511,6 +1511,8 @@ dept_head_ribbon = string(default="Department Head") dealer_ribbon = string(default="Shopkeep") panelist_ribbon = string(default="Panelist") under_13 = string(default="12 & Under") +band = string(default="RockStar") +mivs = string(default="Indie Dev") __many__ = string [[payment]] diff --git a/uber/models/attendee.py b/uber/models/attendee.py index 2e5c94ce2..eb8672bc8 100644 --- a/uber/models/attendee.py +++ b/uber/models/attendee.py @@ -380,6 +380,9 @@ class Attendee(MagModel, TakesPaymentMixin): old_mpoint_exchanges = relationship('OldMPointExchange', backref='attendee') dept_checklist_items = relationship('DeptChecklistItem', backref=backref('attendee', lazy='subquery')) + indie_developer = relationship( + 'IndieDeveloper', backref=backref('attendee', load_on_pending=True), uselist=False) + hotel_eligible = Column(Boolean, default=False, admin_only=True) hotel_requests = relationship('HotelRequests', backref=backref('attendee', load_on_pending=True), uselist=False) room_assignments = relationship('RoomAssignment', backref=backref('attendee', load_on_pending=True)) diff --git a/uber/models/group.py b/uber/models/group.py index 1979049bd..f5bbda52b 100644 --- a/uber/models/group.py +++ b/uber/models/group.py @@ -72,7 +72,7 @@ class Group(MagModel, TakesPaymentMixin): remote_side='Attendee.id', single_parent=True) leader = relationship('Attendee', foreign_keys=leader_id, post_update=True, cascade='all') - studio = relationship('IndieStudio', uselist=False, backref='group') + studio = relationship('IndieStudio', uselist=False, backref='group', cascade='save-update,merge,refresh-expire,expunge') guest = relationship('GuestGroup', backref='group', uselist=False) active_receipt = relationship( 'ModelReceipt', diff --git a/uber/models/mivs.py b/uber/models/mivs.py index 0a80f80f9..f3143ee02 100644 --- a/uber/models/mivs.py +++ b/uber/models/mivs.py @@ -231,12 +231,13 @@ def comped_badges(self): @property def unclaimed_badges(self): claimed_count = len( - [d for d in self.developers if not d.matching_attendee]) + [d for d in self.developers if not d.attendee]) return max(0, self.comped_badges - claimed_count) class IndieDeveloper(MagModel): studio_id = Column(UUID, ForeignKey('indie_studio.id')) + attendee_id = Column(UUID, ForeignKey('attendee.id'), nullable=True) # primary_contact == True just means they receive emails primary_contact = Column(Boolean, default=False) @@ -249,17 +250,11 @@ class IndieDeveloper(MagModel): @property def email_to_address(self): - # Note: this doesn't actually do what we want right now - # because the IndieDeveloper and attendee are not properly linked - if self.matching_attendee: - return self.matching_attendee.email - return self.email + return self.attendee.email if self.attendee else self.email @property def cellphone_num(self): - if self.matching_attendee: - return self.matching_attendee.cellphone - return self.cellphone + return self.attendee.cellphone if self.attendee else self.cellphone @property def full_name(self): diff --git a/uber/site_sections/mivs.py b/uber/site_sections/mivs.py index f19d3759c..b2e51456d 100644 --- a/uber/site_sections/mivs.py +++ b/uber/site_sections/mivs.py @@ -8,7 +8,7 @@ from uber.decorators import all_renderable, csrf_protected from uber.errors import HTTPRedirect from uber.models import Attendee, Group, GuestGroup, IndieDeveloper, IndieStudio -from uber.utils import check, check_csrf +from uber.utils import add_opt, check, check_csrf @all_renderable(public=True) @@ -219,20 +219,24 @@ def confirm(self, session, csrf_token=None, decision=None): session.commit() for dev in developers: if dev.matching_attendee: + add_opt(dev.matching_attendee.ribbon_ints, c.MIVS) if not dev.matching_attendee.group_id: group.attendees.append(dev.matching_attendee) if dev.leader: group.leader_id = dev.matching_attendee.id + dev.matching_attendee.indie_developer = dev else: attendee = Attendee( placeholder=True, badge_type=c.ATTENDEE_BADGE, + ribbon=c.MIVS, paid=c.NEED_NOT_PAY if dev.comped else c.PAID_BY_GROUP, first_name=dev.first_name, last_name=dev.last_name, cellphone=dev.cellphone, email=dev.email ) + attendee.indie_developer = dev group.attendees.append(attendee) session.commit() if dev.leader: diff --git a/uber/templates/mivs_admin/studios.html b/uber/templates/mivs_admin/studios.html index 7a4452381..3ae351b4a 100644 --- a/uber/templates/mivs_admin/studios.html +++ b/uber/templates/mivs_admin/studios.html @@ -26,8 +26,8 @@

{{ studio.name }} - {%- if studio.primary_contacts[0].matching_attendee -%} - {{ studio.primary_contacts[0].full_name }} + {%- if studio.primary_contacts[0].attendee -%} + {{ studio.primary_contacts[0].full_name }} {%- else -%} {{ studio.primary_contacts[0].full_name }} {%- endif %}