diff --git a/information_system_and_programming/term_5/db_management_and_automation/main.py b/information_system_and_programming/term_5/db_management_and_automation/main.py new file mode 100644 index 0000000..e69de29 diff --git a/information_system_and_programming/term_5/db_management_and_automation/poetry.lock b/information_system_and_programming/term_5/db_management_and_automation/poetry.lock index 7c036dc..863200f 100644 --- a/information_system_and_programming/term_5/db_management_and_automation/poetry.lock +++ b/information_system_and_programming/term_5/db_management_and_automation/poetry.lock @@ -401,6 +401,20 @@ files = [ [package.extras] test = ["pytest (>=6)"] +[[package]] +name = "faker" +version = "22.1.0" +description = "Faker is a Python package that generates fake data for you." +optional = false +python-versions = ">=3.8" +files = [ + {file = "Faker-22.1.0-py3-none-any.whl", hash = "sha256:d1b8fe8e8fc96d816294a301741940c2229dcf1f5dd1231805666e4005cc6353"}, + {file = "Faker-22.1.0.tar.gz", hash = "sha256:3cd0e04ed7da1bb8037afc40d1127d19e0ac4afac247a1fe1d8dde9b5c6d6e5b"}, +] + +[package.dependencies] +python-dateutil = ">=2.4" + [[package]] name = "fastapi" version = "0.108.0" @@ -1228,6 +1242,20 @@ pytest = ">=4.6" [package.extras] testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtualenv"] +[[package]] +name = "python-dateutil" +version = "2.8.2" +description = "Extensions to the standard Python datetime module" +optional = false +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,>=2.7" +files = [ + {file = "python-dateutil-2.8.2.tar.gz", hash = "sha256:0123cacc1627ae19ddf3c27a5de5bd67ee4586fbdd6440d9748f8abb483d3e86"}, + {file = "python_dateutil-2.8.2-py2.py3-none-any.whl", hash = "sha256:961d03dc3453ebbc59dbdea9e4e11c5651520a876d0f4db161e8674aae935da9"}, +] + +[package.dependencies] +six = ">=1.5" + [[package]] name = "python-dotenv" version = "1.0.0" @@ -1315,6 +1343,17 @@ files = [ {file = "PyYAML-6.0.1.tar.gz", hash = "sha256:bfdf460b1736c775f2ba9f6a92bca30bc2095067b8a9d77876d1fad6cc3b4a43"}, ] +[[package]] +name = "six" +version = "1.16.0" +description = "Python 2 and 3 compatibility utilities" +optional = false +python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*" +files = [ + {file = "six-1.16.0-py2.py3-none-any.whl", hash = "sha256:8abb2f1d86890a2dfb989f9a77cfcfd3e47c2a354b01111771326f8aa26e0254"}, + {file = "six-1.16.0.tar.gz", hash = "sha256:1e61c37477a1626458e36f7b1d82aa5c9b094fa4802892072e49de9c60c4c926"}, +] + [[package]] name = "sniffio" version = "1.3.0" @@ -1767,4 +1806,4 @@ files = [ [metadata] lock-version = "2.0" python-versions = "^3.10" -content-hash = "016b51f25ab994435bb7d61752487fabe74646550c2ce91ea1ebe70b39afd19a" +content-hash = "2b6a8e175a90e665f12a3ebec8849fa4741e032c3e15f0133efb01b80aaa0cff" diff --git a/information_system_and_programming/term_5/db_management_and_automation/pyproject.toml b/information_system_and_programming/term_5/db_management_and_automation/pyproject.toml index 1215f22..f4a6cee 100644 --- a/information_system_and_programming/term_5/db_management_and_automation/pyproject.toml +++ b/information_system_and_programming/term_5/db_management_and_automation/pyproject.toml @@ -20,6 +20,7 @@ pytest = "^7.4.4" flake8 = "^7.0.0" mypy = "^1.8.0" pytest-cov = "^4.1.0" +faker = "^22.1.0" [tool.pytest.ini_options] pythonpath = ". src" diff --git a/information_system_and_programming/term_5/db_management_and_automation/src/app.py b/information_system_and_programming/term_5/db_management_and_automation/src/app.py index 51e6882..a09ea2f 100644 --- a/information_system_and_programming/term_5/db_management_and_automation/src/app.py +++ b/information_system_and_programming/term_5/db_management_and_automation/src/app.py @@ -13,10 +13,10 @@ async def generate_test_data(): Создание БД и наполнение ее данными """ from backend.database import create_db_and_tables - from backend.queries import UserORM + from backend.queries import Crud await create_db_and_tables() - await UserORM.insert_admin() + await Crud.insert_demo_data() def create_app(): diff --git a/information_system_and_programming/term_5/db_management_and_automation/src/backend/models.py b/information_system_and_programming/term_5/db_management_and_automation/src/backend/models.py index cd8b98b..8af8b0d 100644 --- a/information_system_and_programming/term_5/db_management_and_automation/src/backend/models.py +++ b/information_system_and_programming/term_5/db_management_and_automation/src/backend/models.py @@ -1,5 +1,6 @@ from datetime import datetime -from typing import List, Annotated +import enum +from typing import List, Annotated, Optional from fastapi_users.db import SQLAlchemyBaseUserTable from sqlalchemy import ForeignKey, text @@ -7,6 +8,7 @@ from sqlalchemy.orm import Mapped, mapped_column, relationship, DeclarativeBase intpk = Annotated[int, mapped_column(primary_key=True)] +str_25 = Annotated[str, 25] created_at = Annotated[ datetime, mapped_column(server_default=text("TIMEZONE('utc', now())")), @@ -24,6 +26,17 @@ class Base(DeclarativeBase): pass +class UserRoles(enum.Enum): + """ + Доступные роли юзеров/клиентов + """ + + admin = "Администратор" + director = "Руководитель" + worker = "Работник" + client = "Клиент" + + class UserRoleAssociation(Base): """ Модель таблицы связи Many2Many для Role & User @@ -49,7 +62,7 @@ class Role(Base): __tablename__ = "role" id: Mapped[intpk] - role: Mapped[str] + role: Mapped[Optional[UserRoles]] class User(SQLAlchemyBaseUserTable[int], Base): @@ -59,13 +72,22 @@ class User(SQLAlchemyBaseUserTable[int], Base): __tablename__ = "user" id: Mapped[intpk] - roles: Mapped[List["UserRoleAssociation"]] = relationship() + name: Mapped[str_25] + patronim: Mapped[str_25] + last_name: Mapped[str_25] + roles: Mapped[List["Role"]] = relationship( + secondary="user_role_association", + ) + equipment: Mapped[List["Equipment"]] = relationship() + eq_locations: Mapped[List["UserLocationAssociation"]] = relationship() -class ClientLocationAssociation(Base): - __tablename__ = "client_location_association" +class UserLocationAssociation(Base): + """таблица связи Many2Many между user & location""" + + __tablename__ = "user_location_association" client_id: Mapped[int] = mapped_column( - ForeignKey("client.id"), + ForeignKey("user.id"), primary_key=True, ) location_id: Mapped[int] = mapped_column( @@ -74,18 +96,6 @@ class ClientLocationAssociation(Base): location: Mapped["Location"] = relationship() -class Client(Base): - """ - Клиенты и отделы организации у которых обслуживается оборудование - """ - - __tablename__ = "client" - id: Mapped[intpk] - name: Mapped[str] - equipment: Mapped[int] - locations: Mapped[List[ClientLocationAssociation]] = relationship() - - class Location(Base): """ Адреса клиентов где установленно оборудование @@ -98,11 +108,14 @@ class Location(Base): class Equipment(Base): + """ """ + __tablename__ = "equipment" id: Mapped[intpk] name: Mapped[str] eq_type: Mapped[int] - # location: Mapped[List["Location"]] = relationship() put_into_operation_at: Mapped[datetime] - # user_id: Mapped[int] = mapped_column(ForeignKey("user.id")) - # child: Mapped["User"] = relationship() + owner_id: Mapped[int] = mapped_column(ForeignKey("user.id")) + # Определение связи many2one + location_id: Mapped[int] = mapped_column(ForeignKey("location.id")) + location: Mapped["Location"] = relationship() diff --git a/information_system_and_programming/term_5/db_management_and_automation/src/backend/queries.py b/information_system_and_programming/term_5/db_management_and_automation/src/backend/queries.py index d6848ce..e3ac10a 100644 --- a/information_system_and_programming/term_5/db_management_and_automation/src/backend/queries.py +++ b/information_system_and_programming/term_5/db_management_and_automation/src/backend/queries.py @@ -1,18 +1,78 @@ +from faker import Faker from backend.database import async_session_maker -from backend.models import User +import backend.models as models -class UserORM: +class Crud: @staticmethod - async def insert_admin(): + async def insert_demo_data(): async with async_session_maker() as session: - admin = User( + fake = Faker(["ru_RU"]) + + all_role = [ + models.Role(role="admin"), + models.Role(role="director"), + models.Role(role="worker"), + models.Role(role="client"), + ] + + session.add_all(all_role) + await session.flush() + + admin = models.User( email="admin@mail.com", - hashed_password="sdfasdfasdf", + hashed_password="admin", is_active=True, is_superuser=True, is_verified=True, + roles=all_role, + ) + + director = models.User( + name=fake.first_name_male(), + email="director@mail.com", + hashed_password="director", + roles=all_role[1:3], + ) + + worker1 = models.User( + email="worker1@mail.com", + hashed_password="worker1", + roles=all_role[2:3], + ) + worker2 = models.User( + email="worker2@mail.com", + hashed_password="worker2", + roles=all_role[2:3], + ) + client1 = models.User( + email="client1@mail.com", + hashed_password="client1", + roles=all_role[3:], + ) + client2 = models.User( + email="client2@mail.com", + hashed_password="client2", + roles=all_role[3:], + ) + client3 = models.User( + email="client3@mail.com", + hashed_password="client3", + roles=all_role[3:], + ) + + for _ in range(10): + print(fake.address()) + + session.add_all( + [ + admin, + director, + worker1, + worker2, + client1, + client2, + client3, + ] ) - session.add(admin) - # flush взаимодействует с БД, поэтому пишем await await session.commit()