diff --git a/app/models.py b/app/models.py index 86d5e664..3bbd8f88 100644 --- a/app/models.py +++ b/app/models.py @@ -413,6 +413,14 @@ class User(Base, ModelMixin, UserMixin, PasswordOracle): sa.Boolean, default=False, nullable=False, server_default="0" ) + # user can use the phone feature + can_use_phone = sa.Column( + sa.Boolean, default=False, nullable=False, server_default="0" + ) + + # in minutes + phone_quota = sa.Column(sa.Integer, nullable=True) + @property def directory_quota(self): return min( @@ -2679,3 +2687,56 @@ class DeletedSubdomain(Base, ModelMixin): __tablename__ = "deleted_subdomain" domain = sa.Column(sa.String(128), unique=True, nullable=False) + + +# region Phone +class PhoneCountry(Base, ModelMixin): + __tablename__ = "phone_country" + + name = sa.Column(sa.String(128), unique=True, nullable=False) + + +class PhoneNumber(Base, ModelMixin): + __tablename__ = "phone_number" + + country_id = sa.Column( + sa.ForeignKey(PhoneCountry.id, ondelete="cascade"), nullable=False + ) + + # with country code, e.g. +33612345678 + number = sa.Column(sa.String(128), unique=True, nullable=False) + + active = sa.Column(sa.Boolean, nullable=False, default=True) + + country = orm.relationship(PhoneCountry) + + +class PhoneReservation(Base, ModelMixin): + __tablename__ = "phone_reservation" + + number_id = sa.Column( + sa.ForeignKey(PhoneNumber.id, ondelete="cascade"), nullable=False + ) + + user_id = sa.Column(sa.ForeignKey(User.id, ondelete="cascade"), nullable=False) + + number = orm.relationship(PhoneNumber) + + start = sa.Column(ArrowType, nullable=False) + end = sa.Column(ArrowType, nullable=False) + + +class PhoneMessage(Base, ModelMixin): + __tablename__ = "phone_message" + + number_id = sa.Column( + sa.ForeignKey(PhoneNumber.id, ondelete="cascade"), nullable=False + ) + + from_number = sa.Column(sa.String(128), nullable=False) + body = sa.Column(sa.Text) + + number = orm.relationship(PhoneNumber) + + +# endregion diff --git a/migrations/versions/2021_120216_ad467baf7ec8_.py b/migrations/versions/2021_120216_ad467baf7ec8_.py new file mode 100644 index 00000000..9c009119 --- /dev/null +++ b/migrations/versions/2021_120216_ad467baf7ec8_.py @@ -0,0 +1,76 @@ +"""empty message + +Revision ID: ad467baf7ec8 +Revises: 4b483a762fed +Create Date: 2021-12-02 16:32:50.884324 + +""" +import sqlalchemy_utils +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision = 'ad467baf7ec8' +down_revision = '4b483a762fed' +branch_labels = None +depends_on = None + + +def upgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('phone_country', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True), + sa.Column('name', sa.String(length=128), nullable=False), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('name') + ) + op.create_table('phone_number', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True), + sa.Column('country_id', sa.Integer(), nullable=False), + sa.Column('number', sa.String(length=128), nullable=False), + sa.Column('active', sa.Boolean(), nullable=False), + sa.ForeignKeyConstraint(['country_id'], ['phone_country.id'], ondelete='cascade'), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('number') + ) + op.create_table('phone_message', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True), + sa.Column('number_id', sa.Integer(), nullable=False), + sa.Column('from_number', sa.String(length=128), nullable=False), + sa.Column('body', sa.Text(), nullable=True), + sa.ForeignKeyConstraint(['number_id'], ['phone_number.id'], ondelete='cascade'), + sa.PrimaryKeyConstraint('id') + ) + op.create_table('phone_reservation', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('created_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.Column('updated_at', sqlalchemy_utils.types.arrow.ArrowType(), nullable=True), + sa.Column('number_id', sa.Integer(), nullable=False), + sa.Column('user_id', sa.Integer(), nullable=False), + sa.Column('start', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.Column('end', sqlalchemy_utils.types.arrow.ArrowType(), nullable=False), + sa.ForeignKeyConstraint(['number_id'], ['phone_number.id'], ondelete='cascade'), + sa.ForeignKeyConstraint(['user_id'], ['users.id'], ondelete='cascade'), + sa.PrimaryKeyConstraint('id') + ) + op.add_column('users', sa.Column('can_use_phone', sa.Boolean(), server_default='0', nullable=False)) + op.add_column('users', sa.Column('phone_quota', sa.Integer(), nullable=True)) + # ### end Alembic commands ### + + +def downgrade(): + # ### commands auto generated by Alembic - please adjust! ### + op.drop_column('users', 'phone_quota') + op.drop_column('users', 'can_use_phone') + op.drop_table('phone_reservation') + op.drop_table('phone_message') + op.drop_table('phone_number') + op.drop_table('phone_country') + # ### end Alembic commands ###