diff --git a/7project/backend/alembic.ini b/7project/backend/alembic.ini index c6931a7..6dca9ab 100644 --- a/7project/backend/alembic.ini +++ b/7project/backend/alembic.ini @@ -11,7 +11,7 @@ script_location = %(here)s/alembic # Uncomment the line below if you want the files to be prepended with date and time # see https://alembic.sqlalchemy.org/en/latest/tutorial.html#editing-the-ini-file # for all available tokens -# file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s +file_template = %%(year)d_%%(month).2d_%%(day).2d_%%(hour).2d%%(minute).2d-%%(rev)s_%%(slug)s # sys.path path, will be prepended to sys.path if present. # defaults to the current working directory. for multiple paths, the path separator diff --git a/7project/backend/alembic/versions/81f275275556_init_migration.py b/7project/backend/alembic/versions/2025_10_09_1456-63e072f09836_add_categories.py similarity index 60% rename from 7project/backend/alembic/versions/81f275275556_init_migration.py rename to 7project/backend/alembic/versions/2025_10_09_1456-63e072f09836_add_categories.py index 097cc09..1ddf813 100644 --- a/7project/backend/alembic/versions/81f275275556_init_migration.py +++ b/7project/backend/alembic/versions/2025_10_09_1456-63e072f09836_add_categories.py @@ -1,8 +1,8 @@ -"""Init migration +"""add categories -Revision ID: 81f275275556 +Revision ID: 63e072f09836 Revises: -Create Date: 2025-09-24 17:39:25.346690 +Create Date: 2025-10-09 14:56:14.653249 """ from typing import Sequence, Union @@ -13,7 +13,7 @@ import sqlalchemy as sa # revision identifiers, used by Alembic. -revision: str = '81f275275556' +revision: str = '63e072f09836' down_revision: Union[str, Sequence[str], None] = None branch_labels: Union[str, Sequence[str], None] = None depends_on: Union[str, Sequence[str], None] = None @@ -22,12 +22,6 @@ depends_on: Union[str, Sequence[str], None] = None def upgrade() -> None: """Upgrade schema.""" # ### commands auto generated by Alembic - please adjust! ### - op.create_table('transaction', - sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), - sa.Column('amount', sa.Float(), nullable=False), - sa.Column('description', sa.String(length=255), nullable=True), - sa.PrimaryKeyConstraint('id') - ) op.create_table('user', sa.Column('first_name', sa.String(length=100), nullable=True), sa.Column('last_name', sa.String(length=100), nullable=True), @@ -40,13 +34,38 @@ def upgrade() -> None: sa.PrimaryKeyConstraint('id') ) op.create_index(op.f('ix_user_email'), 'user', ['email'], unique=True) + 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('transaction', + sa.Column('id', sa.Integer(), autoincrement=True, nullable=False), + sa.Column('amount', sa.Float(), 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') + ) + 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('transaction') + op.drop_table('categories') op.drop_index(op.f('ix_user_email'), table_name='user') op.drop_table('user') - op.drop_table('transaction') # ### end Alembic commands ### diff --git a/7project/backend/alembic/versions/2025_10_09_1514-390041bd839e_update_categories_unique.py b/7project/backend/alembic/versions/2025_10_09_1514-390041bd839e_update_categories_unique.py new file mode 100644 index 0000000..ffcc861 --- /dev/null +++ b/7project/backend/alembic/versions/2025_10_09_1514-390041bd839e_update_categories_unique.py @@ -0,0 +1,34 @@ +"""update categories unique + +Revision ID: 390041bd839e +Revises: 63e072f09836 +Create Date: 2025-10-09 15:14:31.557686 + +""" +from typing import Sequence, Union + +from alembic import op +import sqlalchemy as sa + + +# revision identifiers, used by Alembic. +revision: str = '390041bd839e' +down_revision: Union[str, Sequence[str], None] = '63e072f09836' +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.drop_index(op.f('name'), table_name='categories') + op.create_unique_constraint('uix_name_user_id', 'categories', ['name', 'user_id']) + # ### end Alembic commands ### + + +def downgrade() -> None: + """Downgrade schema.""" + # ### commands auto generated by Alembic - please adjust! ### + op.drop_constraint('uix_name_user_id', 'categories', type_='unique') + op.create_index(op.f('name'), 'categories', ['name'], unique=True) + # ### 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..bd766a3 --- /dev/null +++ b/7project/backend/app/models/categories.py @@ -0,0 +1,25 @@ +from fastapi_users_db_sqlalchemy import GUID +from sqlalchemy import Column, Integer, String, ForeignKey, Table, UniqueConstraint +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" + __table_args__ = ( + UniqueConstraint("name", "user_id", name="uix_name_user_id"), + ) + id = Column(Integer, primary_key=True, autoincrement=True) + name = Column(String(length=100), nullable=False) + description = Column(String(length=255), nullable=True) + user_id = Column(GUID, ForeignKey("user.id"), nullable=False) + user = relationship("User", back_populates="categories") + transactions = relationship("Transaction", secondary=association_table, back_populates="categories") diff --git a/7project/backend/app/models/transaction.py b/7project/backend/app/models/transaction.py index bc13565..f260400 100644 --- a/7project/backend/app/models/transaction.py +++ b/7project/backend/app/models/transaction.py @@ -1,9 +1,17 @@ -from sqlalchemy import Column, Integer, String, Float +from fastapi_users_db_sqlalchemy import GUID +from sqlalchemy import Column, Integer, String, Float, ForeignKey +from sqlalchemy.orm import relationship from app.core.base import Base +from app.models.categories import association_table + 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") + categories = relationship("Category", secondary=association_table, 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/charts/myapp-chart/templates/app-deployment.yaml b/7project/charts/myapp-chart/templates/app-deployment.yaml index 9011d46..1d264ab 100644 --- a/7project/charts/myapp-chart/templates/app-deployment.yaml +++ b/7project/charts/myapp-chart/templates/app-deployment.yaml @@ -25,7 +25,7 @@ spec: - containerPort: {{ .Values.app.port }} env: - name: MARIADB_HOST - value: {{ printf "%s.%s.svc.cluster.local" .Values.mariadb.mariaDbRef.name .Values.mariadb.mariaDbRef.namespace | quote }} + value: "mariadb-repl-maxscale-internal.mariadb-operator.svc.cluster.local" - name: MARIADB_PORT value: '3306' - name: MARIADB_DB 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 diff --git a/7project/tofu/modules/maxscale/charts/maxscale-helm/Chart.yaml b/7project/tofu/modules/maxscale/charts/maxscale-helm/Chart.yaml index 15afe88..c78c909 100644 --- a/7project/tofu/modules/maxscale/charts/maxscale-helm/Chart.yaml +++ b/7project/tofu/modules/maxscale/charts/maxscale-helm/Chart.yaml @@ -1,4 +1,4 @@ apiVersion: v2 name: maxscale-helm -version: 1.0.7 +version: 1.0.8 description: Helm chart for MaxScale related Kubernetes manifests diff --git a/7project/tofu/modules/maxscale/charts/maxscale-helm/templates/phpmyadmin-deployment.yaml b/7project/tofu/modules/maxscale/charts/maxscale-helm/templates/phpmyadmin-deployment.yaml index 4a0156c..1ee7b38 100644 --- a/7project/tofu/modules/maxscale/charts/maxscale-helm/templates/phpmyadmin-deployment.yaml +++ b/7project/tofu/modules/maxscale/charts/maxscale-helm/templates/phpmyadmin-deployment.yaml @@ -28,7 +28,7 @@ spec: - name: DATABASE_ENABLE_SSL value: "yes" - name: DATABASE_HOST - value: "mariadb-repl" + value: "mariadb-repl-maxscale-internal" - name: DATABASE_PORT_NUMBER value: "3306" - name: PHPMYADMIN_ALLOW_NO_PASSWORD diff --git a/7project/tofu/modules/maxscale/main.tf b/7project/tofu/modules/maxscale/main.tf index 2b44909..af5a401 100644 --- a/7project/tofu/modules/maxscale/main.tf +++ b/7project/tofu/modules/maxscale/main.tf @@ -58,7 +58,7 @@ resource "helm_release" "mariadb-operator" { resource "helm_release" "maxscale_helm" { name = "maxscale-helm" chart = "${path.module}/charts/maxscale-helm" - version = "1.0.7" + version = "1.0.8" depends_on = [ helm_release.mariadb-operator-crds, kubectl_manifest.secrets ] timeout = 3600