fixed migrations

This commit is contained in:
2025-06-02 16:11:56 +02:00
parent c95a1c456b
commit 4dbaa27cba
98 changed files with 399 additions and 109 deletions

View File

@@ -7,6 +7,7 @@ Create Date: 2025-06-02 14:10:54.033943
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,18 +19,23 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('key_value_settings',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('key', sa.String(length=100), nullable=False),
sa.Column('value', sa.Text(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('key')
)
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'key_value_settings' not in tables:
op.create_table('key_value_settings',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('key', sa.String(length=100), nullable=False),
sa.Column('value', sa.Text(), nullable=True),
sa.Column('updated_at', sa.DateTime(), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('key')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('key_value_settings')
# ### end Alembic commands ###
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-26 14:00:05.521776
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -2,11 +2,12 @@
Revision ID: 1c297825e3a9
Revises:
Create Date: 2025-05-23 08:39:40.494853
Create Date: 2025-06-02 13:26:30.353000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -17,17 +18,24 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=150), nullable=False),
sa.Column('email', sa.String(length=150), nullable=False),
sa.Column('password_hash', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('username')
)
# ### end Alembic commands ###
# Check if the table exists before creating it
conn = op.get_bind()
inspector = sa.inspect(conn)
if 'user' not in inspector.get_table_names():
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'user' not in tables:
op.create_table('user',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('username', sa.String(length=150), nullable=False),
sa.Column('email', sa.String(length=150), nullable=False),
sa.Column('password_hash', sa.String(length=128), nullable=True),
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email'),
sa.UniqueConstraint('username')
)
def downgrade():

View File

@@ -7,6 +7,7 @@ Create Date: 2025-06-02 09:04:39.972021
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('mails',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'mails' not in tables:
op.create_table('mails',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('recipient', sa.String(length=150), nullable=False),
sa.Column('subject', sa.String(length=200), nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 16:10:53.731035
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 21:44:58.832286
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,17 +19,22 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('room_member_permissions',
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('can_view', sa.Boolean(), nullable=False),
sa.Column('can_upload', sa.Boolean(), nullable=False),
sa.Column('can_delete', sa.Boolean(), nullable=False),
sa.Column('can_share', sa.Boolean(), nullable=False),
sa.ForeignKeyConstraint(['room_id'], ['room.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('room_id', 'user_id')
)
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'room_member_permissions' not in tables:
op.create_table('room_member_permissions',
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('can_view', sa.Boolean(), nullable=False),
sa.Column('can_upload', sa.Boolean(), nullable=False),
sa.Column('can_delete', sa.Boolean(), nullable=False),
sa.Column('can_share', sa.Boolean(), nullable=False),
sa.ForeignKeyConstraint(['room_id'], ['room.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('room_id', 'user_id')
)
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 21:27:17.497481
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,15 +19,24 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('room_members',
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['room_id'], ['room.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('room_id', 'user_id')
)
with op.batch_alter_table('room', schema=None) as batch_op:
batch_op.drop_column('is_private')
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'room_members' not in tables:
op.create_table('room_members',
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['room_id'], ['room.id'], ),
sa.ForeignKeyConstraint(['user_id'], ['user.id'], ),
sa.PrimaryKeyConstraint('room_id', 'user_id')
)
# Check if is_private column exists before dropping it
columns = [col['name'] for col in inspector.get_columns('room')]
if 'is_private' in columns:
with op.batch_alter_table('room', schema=None) as batch_op:
batch_op.drop_column('is_private')
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 21:25:27.880150
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,16 +19,21 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('room',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('created_by', sa.Integer(), nullable=False),
sa.Column('is_private', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['created_by'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'room' not in tables:
op.create_table('room',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
sa.Column('created_at', sa.DateTime(), nullable=True),
sa.Column('created_by', sa.Integer(), nullable=False),
sa.Column('is_private', sa.Boolean(), nullable=True),
sa.ForeignKeyConstraint(['created_by'], ['user.id'], ),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 09:24:23.926302
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,12 +19,21 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
conn = op.get_bind()
inspector = inspect(conn)
columns = [col['name'] for col in inspector.get_columns('user')]
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('phone', sa.String(length=20), nullable=True))
batch_op.add_column(sa.Column('company', sa.String(length=100), nullable=True))
batch_op.add_column(sa.Column('position', sa.String(length=100), nullable=True))
batch_op.add_column(sa.Column('notes', sa.Text(), nullable=True))
batch_op.add_column(sa.Column('is_active', sa.Boolean(), nullable=True))
if 'phone' not in columns:
batch_op.add_column(sa.Column('phone', sa.String(length=20), nullable=True))
if 'company' not in columns:
batch_op.add_column(sa.Column('company', sa.String(length=100), nullable=True))
if 'position' not in columns:
batch_op.add_column(sa.Column('position', sa.String(length=100), nullable=True))
if 'notes' not in columns:
batch_op.add_column(sa.Column('notes', sa.Text(), nullable=True))
if 'is_active' not in columns:
batch_op.add_column(sa.Column('is_active', sa.Boolean(), nullable=True))
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-06-02 08:25:48.241102
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -24,7 +25,12 @@ def upgrade():
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('template_variables',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'template_variables' not in tables:
op.create_table('template_variables',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('notification_type', sa.VARCHAR(length=50), autoincrement=False, nullable=False),
sa.Column('variable_name', sa.VARCHAR(length=50), autoincrement=False, nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-24 10:07:02.159730
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('room_file',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'room_file' not in tables:
op.create_table('room_file',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-24 18:14:38.320999
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:05:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.sql import text

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-25 10:03:03.423064
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-26 10:42:17.287566
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:15:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.sql import text

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-25 21:16:39.683736
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('site_settings',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'site_settings' not in tables:
op.create_table('site_settings',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('primary_color', sa.String(length=7), nullable=True),
sa.Column('secondary_color', sa.String(length=7), nullable=True),
@@ -31,7 +37,12 @@ def upgrade():
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('color_settings',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'color_settings' not in tables:
op.create_table('color_settings',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('primary_color', sa.VARCHAR(length=7), autoincrement=False, nullable=True),
sa.Column('secondary_color', sa.VARCHAR(length=7), autoincrement=False, nullable=True),

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# Create conversation table first
op.create_table('conversation',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'conversation' not in tables:
op.create_table('conversation',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('description', sa.Text(), nullable=True),
@@ -29,7 +35,12 @@ def upgrade():
)
# Create conversation_members table
op.create_table('conversation_members',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'conversation_members' not in tables:
op.create_table('conversation_members',
sa.Column('conversation_id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.ForeignKeyConstraint(['conversation_id'], ['conversation.id'], ),
@@ -38,7 +49,12 @@ def upgrade():
)
# Create message table
op.create_table('message',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'message' not in tables:
op.create_table('message',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('content', sa.Text(), nullable=False),
sa.Column('created_at', sa.DateTime(), nullable=True),

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:45:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
revision = 'add_deleted_by_to_room_file'

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:30:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
revision = 'add_deleted_column_to_room_file'

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -17,7 +18,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('trashed_file',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'trashed_file' not in tables:
op.create_table('trashed_file',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('room_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-24 08:36:03.426879
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-26 11:14:05.629795
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-24 12:32:19.239241
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -8,6 +8,7 @@ Create Date: 2025-05-23 19:28:16.977187
from alembic import op
import sqlalchemy as sa
from sqlalchemy.dialects import postgresql
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
revision = 'c21f243b3640'
@@ -19,8 +20,13 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('contact')
conn = op.get_bind()
inspector = inspect(conn)
columns = [col['name'] for col in inspector.get_columns('user')]
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('profile_picture', sa.String(length=255), nullable=True))
if 'profile_picture' not in columns:
batch_op.add_column(sa.Column('profile_picture', sa.String(length=255), nullable=True))
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 16:00:09.905001
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,8 +19,13 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
conn = op.get_bind()
inspector = inspect(conn)
columns = [col['name'] for col in inspector.get_columns('user')]
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('last_name', sa.String(length=150), nullable=True))
if 'last_name' not in columns:
batch_op.add_column(sa.Column('last_name', sa.String(length=150), nullable=True))
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-06-01 20:09:08.019884
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('email_templates',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'email_templates' not in tables:
op.create_table('email_templates',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=100), nullable=False),
sa.Column('subject', sa.String(length=200), nullable=False),
@@ -54,7 +60,12 @@ def downgrade():
type_=postgresql.JSONB(astext_type=sa.Text()),
existing_nullable=True)
op.create_table('notification',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'notification' not in tables:
op.create_table('notification',
sa.Column('id', sa.INTEGER(), autoincrement=True, nullable=False),
sa.Column('user_id', sa.INTEGER(), autoincrement=False, nullable=False),
sa.Column('title', sa.VARCHAR(length=255), autoincrement=False, nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-25 21:08:37.158900
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('color_settings',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'color_settings' not in tables:
op.create_table('color_settings',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('primary_color', sa.String(length=7), nullable=True),
sa.Column('secondary_color', sa.String(length=7), nullable=True),

View File

@@ -7,6 +7,7 @@ Create Date: 2024-03-19 10:00:00.000000
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
from sqlalchemy.dialects import postgresql
# revision identifiers, used by Alembic.
@@ -17,7 +18,12 @@ depends_on = None
def upgrade():
# Create user_starred_file table
op.create_table('user_starred_file',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'user_starred_file' not in tables:
op.create_table('user_starred_file',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('user_id', sa.Integer(), nullable=False),
sa.Column('file_id', sa.Integer(), nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 08:45:00.693155
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-23 08:55:10.537722
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -35,9 +36,17 @@ def upgrade():
sa.PrimaryKeyConstraint('id'),
sa.UniqueConstraint('email')
)
# Check if columns exist before adding them
conn = op.get_bind()
inspector = inspect(conn)
columns = [col['name'] for col in inspector.get_columns('user')]
with op.batch_alter_table('user', schema=None) as batch_op:
batch_op.add_column(sa.Column('is_admin', sa.Boolean(), nullable=True))
batch_op.add_column(sa.Column('created_at', sa.DateTime(), nullable=True))
if 'is_admin' not in columns:
batch_op.add_column(sa.Column('is_admin', sa.Boolean(), nullable=True))
if 'created_at' not in columns:
batch_op.add_column(sa.Column('created_at', sa.DateTime(), nullable=True))
# ### end Alembic commands ###

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-26 15:00:18.557702
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.
@@ -18,7 +19,12 @@ depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('message_attachment',
conn = op.get_bind()
inspector = inspect(conn)
tables = inspector.get_table_names()
if 'message_attachment' not in tables:
op.create_table('message_attachment',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('message_id', sa.Integer(), nullable=False),
sa.Column('name', sa.String(length=255), nullable=False),

View File

@@ -7,6 +7,7 @@ Create Date: 2025-05-26 10:52:32.572951
"""
from alembic import op
import sqlalchemy as sa
from sqlalchemy import inspect
# revision identifiers, used by Alembic.