""" DataFlow Server — Database Engine & Session """ from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from sqlalchemy.orm import Session from models import Base, User, Project, Task, Expense, Document, AIForecast, Notification, SubTask from datetime import datetime, timedelta from passlib.context import CryptContext import uuid import os DATABASE_URL = os.getenv("DATABASE_URL", "sqlite+aiosqlite:///./dataflow.db") engine = create_async_engine(DATABASE_URL, echo=False) AsyncSessionLocal = async_sessionmaker(engine, expire_on_commit=False) pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto") async def get_db() -> AsyncSession: async with AsyncSessionLocal() as session: yield session async def init_db(): """Create tables and seed demo data if empty.""" async with engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) async with AsyncSessionLocal() as db: # Check if already seeded from sqlalchemy import select, text result = await db.execute(select(User).limit(1)) if result.scalar_one_or_none() is not None: return # Already seeded print("Seeding database with demo data...") uid1 = str(uuid.uuid4()) uid2 = str(uuid.uuid4()) uid3 = str(uuid.uuid4()) # Users users = [ User(id=uid1, full_name="Анастасия Иванова", email="nastya@example.com", hashed_password=pwd_context.hash("123456"), position="Проект-менеджер", role="manager"), User(id=uid2, full_name="Алексей Петров", email="alexey@example.com", hashed_password=pwd_context.hash("123456"), position="Backend-разработчик", role="developer"), User(id=uid3, full_name="Мария Сидорова", email="maria@example.com", hashed_password=pwd_context.hash("123456"), position="Frontend-разработчик", role="developer"), ] db.add_all(users) await db.flush() # Projects p1_id = str(uuid.uuid4()) p2_id = str(uuid.uuid4()) projects = [ Project(id=p1_id, name="Мобильное приложение E-Commerce", description="Разработка мобильного приложения для интернет-магазина", start_date=datetime(2026, 1, 15), end_date=datetime(2026, 6, 30), budget=5000000, spent=2750000, status="active", progress=0.55, risk_level="yellow", owner_id=uid1), Project(id=p2_id, name="CRM Система", description="Внедрение CRM системы для отдела продаж", start_date=datetime(2026, 3, 1), end_date=datetime(2026, 8, 31), budget=3200000, spent=800000, status="active", progress=0.25, risk_level="green", owner_id=uid1), ] db.add_all(projects) await db.flush() # Tasks t1_id = str(uuid.uuid4()) t2_id = str(uuid.uuid4()) tasks = [ Task(id=t1_id, title="Разработка API авторизации", project_id=p1_id, status="done", priority="high", assignee_id=uid2, assignee_name="Алексей П.", deadline=datetime(2026, 4, 15), description="Реализовать REST API для регистрации, входа, JWT и 2FA"), Task(id=t2_id, title="Дизайн каталога товаров", project_id=p1_id, status="inProgress", priority="high", assignee_id=uid3, assignee_name="Мария С.", deadline=datetime(2026, 5, 20), description="Разработать UI/UX для каталога с фильтрами"), Task(id=str(uuid.uuid4()), title="Интеграция платежного шлюза", project_id=p1_id, status="todo", priority="critical", assignee_id=uid2, assignee_name="Алексей П.", deadline=datetime(2026, 5, 30), description="Подключить Kaspi Pay и Halyk Bank"), Task(id=str(uuid.uuid4()), title="Анализ требований CRM", project_id=p2_id, status="done", priority="high", assignee_id=uid3, assignee_name="Мария С.", deadline=datetime(2026, 4, 10)), ] db.add_all(tasks) await db.flush() # Subtasks db.add_all([ SubTask(id=str(uuid.uuid4()), task_id=t1_id, title="JWT Token", completed=True), SubTask(id=str(uuid.uuid4()), task_id=t1_id, title="Refresh Token", completed=True), SubTask(id=str(uuid.uuid4()), task_id=t1_id, title="2FA SMS", completed=True), SubTask(id=str(uuid.uuid4()), task_id=t2_id, title="Wireframes", completed=True), SubTask(id=str(uuid.uuid4()), task_id=t2_id, title="Mockups", completed=True), SubTask(id=str(uuid.uuid4()), task_id=t2_id, title="Prototype", completed=False), ]) # Expenses db.add_all([ Expense(id=str(uuid.uuid4()), project_id=p1_id, title="Зарплата разработчиков (Март)", amount=900000, category="personnel", status="approved", date=datetime(2026, 3, 31)), Expense(id=str(uuid.uuid4()), project_id=p1_id, title="Облачный хостинг AWS", amount=150000, category="infrastructure", status="approved", date=datetime(2026, 4, 5)), Expense(id=str(uuid.uuid4()), project_id=p1_id, title="Лицензия Figma Team", amount=85000, category="software", status="approved", date=datetime(2026, 4, 10)), Expense(id=str(uuid.uuid4()), project_id=p1_id, title="Командировка в Астану", amount=120000, category="travel", status="pending", date=datetime(2026, 5, 5)), Expense(id=str(uuid.uuid4()), project_id=p2_id, title="Консультация по 1С", amount=200000, category="training", status="approved", date=datetime(2026, 4, 20)), ]) # Documents db.add_all([ Document(id=str(uuid.uuid4()), project_id=p1_id, name="Техническое задание E-Commerce.pdf", type="pdf", size_bytes=2450000, is_favorite=True), Document(id=str(uuid.uuid4()), project_id=p1_id, name="Смета проекта.xlsx", type="xlsx", size_bytes=340000, is_favorite=True), Document(id=str(uuid.uuid4()), project_id=p1_id, name="Счёт AWS Март 2026.pdf", type="pdf", size_bytes=120000, detected_type="invoice", recognition_confidence=0.97, extracted_text="Сумма: 150 000 KZT\nДата: 31.03.2026\nПоставщик: Amazon Web Services", extracted_amount=150000, extracted_supplier="Amazon Web Services"), ]) # AI Forecasts db.add_all([ AIForecast(id=str(uuid.uuid4()), project_id=p1_id, current_spent=2750000, planned_budget=5000000, risk_level="yellow", overrun_probability=35.0, optimistic_forecast=4600000, realistic_forecast=5200000, pessimistic_forecast=5800000, recommendations='["Оптимизировать расходы на облачную инфраструктуру","Рассмотреть аутсорсинг QA-тестирования","Пересмотреть приоритеты задач","Использовать Open Source альтернативы"]'), AIForecast(id=str(uuid.uuid4()), project_id=p2_id, current_spent=800000, planned_budget=3200000, risk_level="green", overrun_probability=12.0, optimistic_forecast=2800000, realistic_forecast=3100000, pessimistic_forecast=3400000, recommendations='["Проект идёт в рамках бюджета","Рекомендуется создать резерв на интеграцию с 1С"]'), ]) # Notifications db.add_all([ Notification(id=str(uuid.uuid4()), user_id=uid1, title="AI прогноз: Внимание", body="Проект 'E-Commerce' — риск перерасхода 35%", type="ai"), Notification(id=str(uuid.uuid4()), user_id=uid1, title="Новый расход на согласование", body="Командировка в Астану — 120 000 ₸", type="expense"), ]) await db.commit() print("Database seeded successfully!")