diff --git a/7project/backend/alembic/versions/a60134ef6c4c_add_categories.py b/7project/backend/alembic/versions/a60134ef6c4c_add_categories.py new file mode 100644 index 0000000..7c1e599 --- /dev/null +++ b/7project/backend/alembic/versions/a60134ef6c4c_add_categories.py @@ -0,0 +1,48 @@ +"""add categories + +Revision ID: a60134ef6c4c +Revises: c5e9d6c59812 +Create Date: 2025-10-09 14:29:31.170347 + +""" +from typing import Sequence, Union + +import fastapi_users_db_sqlalchemy +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'a60134ef6c4c' +down_revision: Union[str, Sequence[str], None] = 'c5e9d6c59812' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.create_table('categories', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('name', sa.String(length=100), nullable=False), + sa.Column('description', sa.String(length=255), nullable=True), + sa.Column('user_id', fastapi_users_db_sqlalchemy.generics.GUID(), nullable=False), + sa.ForeignKeyConstraint(['user_id'], ['user.id'], ), + sa.PrimaryKeyConstraint('id'), + sa.UniqueConstraint('name') + ) + op.create_table('category_transaction', + sa.Column('id_category', sa.Integer(), nullable=True), + sa.Column('id_transaction', sa.Integer(), nullable=True), + sa.ForeignKeyConstraint(['id_category'], ['categories.id'], ), + sa.ForeignKeyConstraint(['id_transaction'], ['transaction.id'], ) + ) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_table('category_transaction') + op.drop_table('categories') + # ### end Alembic commands ### diff --git a/7project/backend/alembic/versions/c5e9d6c59812_user_transaction_relationship.py b/7project/backend/alembic/versions/c5e9d6c59812_user_transaction_relationship.py new file mode 100644 index 0000000..b88a489 --- /dev/null +++ b/7project/backend/alembic/versions/c5e9d6c59812_user_transaction_relationship.py @@ -0,0 +1,41 @@ +"""User transaction relationship + +Revision ID: c5e9d6c59812 +Revises: 81f275275556 +Create Date: 2025-10-09 14:17:19.983889 + +""" +from typing import Sequence, Union + +import fastapi_users_db_sqlalchemy +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = 'c5e9d6c59812' +down_revision: Union[str, Sequence[str], None] = '81f275275556' +branch_labels: Union[str, Sequence[str], None] = None +depends_on: Union[str, Sequence[str], None] = None + + +def upgrade() -> None: + """Upgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.alter_column('transaction', 'user_id', + existing_type=sa.UUID(), + type_=fastapi_users_db_sqlalchemy.generics.GUID(), + existing_nullable=False) + op.create_foreign_key(None, 'transaction', 'user', ['user_id'], ['id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint(None, 'transaction', type_='foreignkey') + op.alter_column('transaction', 'user_id', + existing_type=fastapi_users_db_sqlalchemy.generics.GUID(), + type_=sa.UUID(), + existing_nullable=False) + # ### end Alembic commands ### diff --git a/7project/backend/app/core/db.py b/7project/backend/app/core/db.py index 40ff77f..9c8cad7 100644 --- a/7project/backend/app/core/db.py +++ b/7project/backend/app/core/db.py @@ -17,6 +17,7 @@ if not DATABASE_URL: # Load all models to register them from app.models.user import User from app.models.transaction import Transaction +from app.models.categories import Category ssl_enabled = os.getenv("MARIADB_HOST", "localhost") != "localhost" connect_args = {"ssl": {"ssl": True}} if ssl_enabled else {} diff --git a/7project/backend/app/models/categories.py b/7project/backend/app/models/categories.py new file mode 100644 index 0000000..641ca2d --- /dev/null +++ b/7project/backend/app/models/categories.py @@ -0,0 +1,22 @@ +from fastapi_users_db_sqlalchemy import GUID +from sqlalchemy import Column, Integer, String, ForeignKey, Table +from sqlalchemy.orm import relationship + +from app.core.base import Base + +association_table = Table( + "category_transaction", + Base.metadata, + Column("id_category", Integer, ForeignKey("categories.id")), + Column("id_transaction", Integer, ForeignKey("transaction.id")) +) + + +class Category(Base): + __tablename__ = "categories" + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(length=100), unique=True, nullable=False) + description = Column(String(length=255), nullable=True) + user_id = Column(GUID, ForeignKey("user.id"), nullable=False) + user = relationship("User", back_populates="categories") + relationship(secondary=association_table) diff --git a/7project/backend/app/models/transaction.py b/7project/backend/app/models/transaction.py index bc13565..39b640d 100644 --- a/7project/backend/app/models/transaction.py +++ b/7project/backend/app/models/transaction.py @@ -1,9 +1,15 @@ -from sqlalchemy import Column, Integer, String, Float +from fastapi_users_db_sqlalchemy import GUID +from sqlalchemy import Column, Integer, String, Float, ForeignKey, UUID +from sqlalchemy.orm import relationship from app.core.base import Base + class Transaction(Base): __tablename__ = "transaction" id = Column(Integer, primary_key=True, autoincrement=True) amount = Column(Float, nullable=False) description = Column(String(length=255), nullable=True) + user_id = Column(GUID, ForeignKey("user.id"), nullable=False) + # Relationship + user = relationship("User", back_populates="transactions") diff --git a/7project/backend/app/models/user.py b/7project/backend/app/models/user.py index 4c0f206..836dddf 100644 --- a/7project/backend/app/models/user.py +++ b/7project/backend/app/models/user.py @@ -1,7 +1,13 @@ from sqlalchemy import Column, String +from sqlalchemy.orm import relationship from fastapi_users.db import SQLAlchemyBaseUserTableUUID from app.core.base import Base + class User(SQLAlchemyBaseUserTableUUID, Base): first_name = Column(String(length=100), nullable=True) last_name = Column(String(length=100), nullable=True) + + # Relationship + transactions = relationship("Transaction", back_populates="user") + categories = relationship("Category", back_populates="user") \ No newline at end of file diff --git a/7project/create_migration.sh b/7project/create_migration.sh index de43ffc..f8e8c04 100644 --- a/7project/create_migration.sh +++ b/7project/create_migration.sh @@ -8,4 +8,8 @@ fi cd backend || { echo "Directory 'backend' does not exist"; exit 1; } alembic revision --autogenerate -m "$1" git add alembic/versions/* +YELLOW='\033[1;33m' +NC='\033[0m' # No Color + +echo -e "${YELLOW}Don't forget to check imports in the new migration file!${NC}" cd - || exit \ No newline at end of file