aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--alembic/versions/5d998cafe1ba_init_database.py55
-rw-r--r--models/__init__.py4
-rw-r--r--models/announcement.py19
-rw-r--r--models/rich_text.py7
-rw-r--r--models/suggest.py23
-rw-r--r--models/user.py15
6 files changed, 114 insertions, 9 deletions
diff --git a/alembic/versions/5d998cafe1ba_init_database.py b/alembic/versions/5d998cafe1ba_init_database.py
new file mode 100644
index 0000000..e55e4ed
--- /dev/null
+++ b/alembic/versions/5d998cafe1ba_init_database.py
@@ -0,0 +1,55 @@
1"""init database
2
3Revision ID: 5d998cafe1ba
4Revises:
5Create Date: 2026-03-23 00:05:14.621886
6
7"""
8from typing import Sequence, Union
9
10from alembic import op
11import sqlalchemy as sa
12
13
14# revision identifiers, used by Alembic.
15revision: str = '5d998cafe1ba'
16down_revision: Union[str, Sequence[str], None] = None
17branch_labels: Union[str, Sequence[str], None] = None
18depends_on: Union[str, Sequence[str], None] = None
19
20
21def upgrade() -> None:
22 """Upgrade schema."""
23 # ### commands auto generated by Alembic - please adjust! ###
24 op.create_table('invoice',
25 sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
26 sa.Column('amount', sa.Float(), nullable=False),
27 sa.Column('datetime', sa.DateTime(), nullable=False),
28 sa.PrimaryKeyConstraint('id', name=op.f('pk_invoice'))
29 )
30 op.create_table('user',
31 sa.Column('id', sa.Integer(), autoincrement=False, nullable=False),
32 sa.Column('role', sa.Enum('REGULAR', 'ADMIN', name='userrole'), nullable=False),
33 sa.Column('vpn_link', sa.String(), nullable=False),
34 sa.PrimaryKeyConstraint('id', name=op.f('pk_user'))
35 )
36 op.create_table('payment',
37 sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
38 sa.Column('user_id', sa.Integer(), nullable=False),
39 sa.Column('invoice_id', sa.Integer(), nullable=False),
40 sa.Column('receipt_file_id', sa.String(), nullable=False),
41 sa.Column('datetime', sa.DateTime(), nullable=False),
42 sa.ForeignKeyConstraint(['invoice_id'], ['invoice.id'], name=op.f('fk_payment_invoice_id_invoice')),
43 sa.ForeignKeyConstraint(['user_id'], ['user.id'], name=op.f('fk_payment_user_id_user')),
44 sa.PrimaryKeyConstraint('id', name=op.f('pk_payment'))
45 )
46 # ### end Alembic commands ###
47
48
49def downgrade() -> None:
50 """Downgrade schema."""
51 # ### commands auto generated by Alembic - please adjust! ###
52 op.drop_table('payment')
53 op.drop_table('user')
54 op.drop_table('invoice')
55 # ### end Alembic commands ###
diff --git a/models/__init__.py b/models/__init__.py
index 70c841d..412f467 100644
--- a/models/__init__.py
+++ b/models/__init__.py
@@ -1,11 +1,15 @@
1# isort: off 1# isort: off
2from .base import BaseTable 2from .base import BaseTable
3from .rich_text import RichText
3from .user import User 4from .user import User
4from .invoce import Invoice 5from .invoce import Invoice
6from .payment import Payment
5# isort: on 7# isort: on
6 8
7__all__ = [ 9__all__ = [
8 "BaseTable", 10 "BaseTable",
9 "User", 11 "User",
10 "Invoice", 12 "Invoice",
13 "Payment",
14 "RichText",
11] 15]
diff --git a/models/announcement.py b/models/announcement.py
index 5f752d7..9a6eef2 100644
--- a/models/announcement.py
+++ b/models/announcement.py
@@ -1,18 +1,19 @@
1from aiogram.types import MessageEntity
2from pydantic import BaseModel
3from sqlalchemy import JSON 1from sqlalchemy import JSON
4from sqlalchemy.orm import Mapped, mapped_column 2from sqlalchemy.orm import Mapped, mapped_column
5 3
6from models import BaseTable 4from models import BaseTable, RichText
7
8
9class Message(BaseModel):
10 text: str
11 entities: list[MessageEntity] = []
12 5
13 6
14class Announcement(BaseTable): 7class Announcement(BaseTable):
15 __tablename__ = "announcement" 8 __tablename__ = "announcement"
16 9
17 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True) 10 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
18 message: Mapped[str] = mapped_column(JSON()) 11 __message: Mapped[str] = mapped_column("message", JSON())
12
13 @property
14 def message(self) -> RichText:
15 return RichText.model_validate_json(self.__message)
16
17 @message.setter
18 def message_set(self, value: RichText) -> None:
19 self.__message = value.model_dump_json()
diff --git a/models/rich_text.py b/models/rich_text.py
new file mode 100644
index 0000000..2b433ec
--- /dev/null
+++ b/models/rich_text.py
@@ -0,0 +1,7 @@
1from aiogram.types import MessageEntity
2from pydantic import BaseModel
3
4
5class RichText(BaseModel):
6 text: str
7 entities: list[MessageEntity] = []
diff --git a/models/suggest.py b/models/suggest.py
new file mode 100644
index 0000000..1ba18a0
--- /dev/null
+++ b/models/suggest.py
@@ -0,0 +1,23 @@
1from sqlalchemy import JSON
2from sqlalchemy.orm import Mapped, mapped_column
3from sqlalchemy.sql.schema import ForeignKey
4
5from models import RichText, User
6from models.base import BaseTable
7
8
9class Suggest(BaseTable):
10 __tablename__ = "suggest"
11
12 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=True)
13 user_id: Mapped[int] = mapped_column(ForeignKey(User.id))
14 suggested_user_id: Mapped[int]
15 __message: Mapped[str] = mapped_column("message", JSON())
16
17 @property
18 def message(self) -> RichText:
19 return RichText.model_validate_json(self.__message)
20
21 @message.setter
22 def message_set(self, value: RichText) -> None:
23 self.__message = value.model_dump_json()
diff --git a/models/user.py b/models/user.py
index 7118725..4983a13 100644
--- a/models/user.py
+++ b/models/user.py
@@ -1,9 +1,24 @@
1from enum import IntEnum
2
1from sqlalchemy.orm import Mapped, mapped_column 3from sqlalchemy.orm import Mapped, mapped_column
2 4
3from models import BaseTable 5from models import BaseTable
4 6
5 7
8class UserRole(IntEnum):
9 REGULAR = 0
10 ADMIN = 1
11
12
6class User(BaseTable): 13class User(BaseTable):
7 __tablename__ = "user" 14 __tablename__ = "user"
8 15
9 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=False) 16 id: Mapped[int] = mapped_column(primary_key=True, autoincrement=False)
17 role: Mapped[UserRole] = mapped_column(default=UserRole.REGULAR)
18 vpn_link: Mapped[str]
19
20 def is_regular(self) -> bool:
21 return self.role >= UserRole.REGULAR
22
23 def is_admin(self) -> bool:
24 return self.role == UserRole.ADMIN