test
This commit is contained in:
		
							parent
							
								
									043386268b
								
							
						
					
					
						commit
						e3860e2490
					
				| 
						 | 
					@ -2,27 +2,14 @@ import os
 | 
				
			||||||
from pydantic_settings import BaseSettings
 | 
					from pydantic_settings import BaseSettings
 | 
				
			||||||
from dotenv import load_dotenv
 | 
					from dotenv import load_dotenv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Load .env file from the backend directory (one level up from core)
 | 
					 | 
				
			||||||
# BASE_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
 | 
					 | 
				
			||||||
# load_dotenv(os.path.join(BASE_DIR, '..', '.env')) # Adjust path if needed
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Or simply let pydantic-settings handle it by default if .env is in the root execution dir
 | 
					 | 
				
			||||||
load_dotenv()
 | 
					load_dotenv()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
class Settings(BaseSettings):
 | 
					class Settings(BaseSettings):
 | 
				
			||||||
    DATABASE_URL: str = "sqlite:///./default.db" # Default value if not in .env
 | 
					    DATABASE_URL: str = "sqlite:///./default.db" 
 | 
				
			||||||
    # Настройки JWT удалены
 | 
					 | 
				
			||||||
    # SECRET_KEY: str = "default_secret"
 | 
					 | 
				
			||||||
    # ALGORITHM: str = "HS256"
 | 
					 | 
				
			||||||
    # ACCESS_TOKEN_EXPIRE_MINUTES: int = 30
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Config:
 | 
					    class Config:
 | 
				
			||||||
        env_file = ".env"
 | 
					        env_file = ".env"
 | 
				
			||||||
        env_file_encoding = 'utf-8'
 | 
					        env_file_encoding = 'utf-8'
 | 
				
			||||||
        # If your .env file is not in the root directory where you run uvicorn,
 | 
					 | 
				
			||||||
        # you might need to specify the path explicitly:
 | 
					 | 
				
			||||||
        # env_file = '../.env' # Example if running from inside 'app' dir
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
settings = Settings() 
 | 
					settings = Settings() 
 | 
				
			||||||
| 
						 | 
					@ -2,17 +2,14 @@ from sqlalchemy import create_engine
 | 
				
			||||||
from sqlalchemy.orm import sessionmaker
 | 
					from sqlalchemy.orm import sessionmaker
 | 
				
			||||||
from app.core.config import settings
 | 
					from app.core.config import settings
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create SQLAlchemy engine
 | 
					 | 
				
			||||||
engine = create_engine(
 | 
					engine = create_engine(
 | 
				
			||||||
    settings.DATABASE_URL,
 | 
					    settings.DATABASE_URL,
 | 
				
			||||||
    # Required for SQLite to prevent issues with FastAPI's async nature
 | 
					    
 | 
				
			||||||
    connect_args={"check_same_thread": False} if "sqlite" in settings.DATABASE_URL else {}
 | 
					    connect_args={"check_same_thread": False} if "sqlite" in settings.DATABASE_URL else {}
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Create a session factory
 | 
					 | 
				
			||||||
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 | 
					SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Dependency to get DB session (we'll use this in routers)
 | 
					 | 
				
			||||||
def get_db():
 | 
					def get_db():
 | 
				
			||||||
    db = SessionLocal()
 | 
					    db = SessionLocal()
 | 
				
			||||||
    try:
 | 
					    try:
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,7 @@ import asyncio
 | 
				
			||||||
import random
 | 
					import random
 | 
				
			||||||
from typing import Dict, Any
 | 
					from typing import Dict, Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Делаем функцию асинхронной
 | 
					
 | 
				
			||||||
async def solve_cutting_problem(input_params: Dict[str, Any]) -> Dict[str, Any]:
 | 
					async def solve_cutting_problem(input_params: Dict[str, Any]) -> Dict[str, Any]:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Асинхронная заглушка для имитации сложного расчета раскройки стекла.
 | 
					    Асинхронная заглушка для имитации сложного расчета раскройки стекла.
 | 
				
			||||||
| 
						 | 
					@ -10,26 +10,23 @@ async def solve_cutting_problem(input_params: Dict[str, Any]) -> Dict[str, Any]:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    print(f"Received input for async fuzzy solver: {input_params}")
 | 
					    print(f"Received input for async fuzzy solver: {input_params}")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Имитация времени расчета с использованием asyncio.sleep
 | 
					 | 
				
			||||||
    delay = random.uniform(0.5, 2.0)
 | 
					    delay = random.uniform(0.5, 2.0)
 | 
				
			||||||
    print(f"Simulating calculation for {delay:.2f} seconds...")
 | 
					    print(f"Simulating calculation for {delay:.2f} seconds...")
 | 
				
			||||||
    await asyncio.sleep(delay) # Используем await asyncio.sleep вместо time.sleep
 | 
					    await asyncio.sleep(delay) 
 | 
				
			||||||
 | 
					  
 | 
				
			||||||
    # Пример выходных данных (остается таким же)
 | 
					 | 
				
			||||||
    output_data = {
 | 
					    output_data = {
 | 
				
			||||||
        "layout": [
 | 
					        "layout": [
 | 
				
			||||||
            {"piece_id": 1, "x": 10, "y": 10, "width": 500, "height": 300},
 | 
					            {"piece_id": 1, "x": 10, "y": 10, "width": 500, "height": 300},
 | 
				
			||||||
            {"piece_id": 2, "x": 520, "y": 10, "width": 400, "height": 300},
 | 
					            {"piece_id": 2, "x": 520, "y": 10, "width": 400, "height": 300},
 | 
				
			||||||
            # ... другие детали раскроя ...
 | 
					            
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "waste_percentage": round(random.uniform(5.0, 15.0), 2),
 | 
					        "waste_percentage": round(random.uniform(5.0, 15.0), 2),
 | 
				
			||||||
        "number_of_cuts": random.randint(5, 20),
 | 
					        "number_of_cuts": random.randint(5, 20),
 | 
				
			||||||
        "processing_time_ms": int(delay * 1000) # Используем задержку как время обработки
 | 
					        "processing_time_ms": int(delay * 1000) 
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Можно добавить логику на основе input_params, если нужно для тестов
 | 
					 | 
				
			||||||
    if input_params.get("optimize_for") == "speed":
 | 
					    if input_params.get("optimize_for") == "speed":
 | 
				
			||||||
         output_data["number_of_cuts"] = random.randint(15, 25) # Больше резов - быстрее?
 | 
					         output_data["number_of_cuts"] = random.randint(15, 25) 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    print(f"Async fuzzy solver generated output: {output_data}")
 | 
					    print(f"Async fuzzy solver generated output: {output_data}")
 | 
				
			||||||
    return output_data 
 | 
					    return output_data 
 | 
				
			||||||
| 
						 | 
					@ -1,37 +1,25 @@
 | 
				
			||||||
from fastapi import FastAPI
 | 
					from fastapi import FastAPI
 | 
				
			||||||
from fastapi.middleware.cors import CORSMiddleware # Импортируем middleware
 | 
					from fastapi.middleware.cors import CORSMiddleware
 | 
				
			||||||
from app.routers import calculation # Импортируем роутер
 | 
					from app.routers import calculation
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app = FastAPI(title="Glass Cutting Optimization API")
 | 
					app = FastAPI(title="Glass Cutting Optimization API")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --- Настройка CORS ---
 | 
					 | 
				
			||||||
# Список разрешенных источников (origins)
 | 
					 | 
				
			||||||
# Для разработки можно разрешить все или указать адрес вашего React-приложения
 | 
					 | 
				
			||||||
origins = [
 | 
					origins = [
 | 
				
			||||||
    "http://localhost",       # Если React запускается на http://localhost:port
 | 
					    "http://localhost",
 | 
				
			||||||
    "http://localhost:3000",  # Стандартный порт для create-react-app
 | 
					    "http://localhost:3000",
 | 
				
			||||||
    "http://localhost:5173",  # Стандартный порт для Vite/React
 | 
					    "http://localhost:5173",
 | 
				
			||||||
    # "http://127.0.0.1:5173", # Можно добавить и IP-адрес
 | 
					 | 
				
			||||||
    # "*" # Разрешить все источники (будьте осторожны в production)
 | 
					 | 
				
			||||||
]
 | 
					]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
app.add_middleware(
 | 
					app.add_middleware(
 | 
				
			||||||
    CORSMiddleware,
 | 
					    CORSMiddleware,
 | 
				
			||||||
    allow_origins=origins, # Указываем разрешенные источники
 | 
					    allow_origins=origins,
 | 
				
			||||||
    allow_credentials=True, # Разрешаем куки (если потребуются в будущем)
 | 
					    allow_credentials=True,
 | 
				
			||||||
    allow_methods=["*"],    # Разрешаем все методы (GET, POST, PUT, etc.)
 | 
					    allow_methods=["*"],
 | 
				
			||||||
    allow_headers=["*"],    # Разрешаем все заголовки
 | 
					    allow_headers=["*"],
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
# --- Конец настройки CORS ---
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Подключаем роутер расчетов
 | 
					 | 
				
			||||||
app.include_router(calculation.router)
 | 
					app.include_router(calculation.router)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@app.get("/")
 | 
					@app.get("/")
 | 
				
			||||||
async def read_root():
 | 
					async def read_root():
 | 
				
			||||||
    return {"message": "Welcome to the Glass Cutting Optimization API"}
 | 
					    return {"message": "Welcome to the Glass Cutting Optimization API"}
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Убедимся, что здесь нет подключения auth роутера
 | 
					 | 
				
			||||||
# from .routers import calculation # Позже подключим calculation
 | 
					 | 
				
			||||||
# app.include_router(calculation.router) 
 | 
					 | 
				
			||||||
| 
						 | 
					@ -2,7 +2,5 @@ from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column
 | 
				
			||||||
from sqlalchemy import Integer
 | 
					from sqlalchemy import Integer
 | 
				
			||||||
from typing import Annotated
 | 
					from typing import Annotated
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Define a base class using SQLAlchemy 2.0 style
 | 
					 | 
				
			||||||
class Base(DeclarativeBase):
 | 
					class Base(DeclarativeBase):
 | 
				
			||||||
    # Define a primary key type annotation for convenience
 | 
					 | 
				
			||||||
    pass
 | 
					    pass
 | 
				
			||||||
| 
						 | 
					@ -8,7 +8,6 @@ from typing import Dict, Any
 | 
				
			||||||
class Calculation(Base):
 | 
					class Calculation(Base):
 | 
				
			||||||
    __tablename__ = "calculations"
 | 
					    __tablename__ = "calculations"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    #
 | 
					 | 
				
			||||||
    id: Mapped[int] = mapped_column(primary_key=True, index=True)
 | 
					    id: Mapped[int] = mapped_column(primary_key=True, index=True)
 | 
				
			||||||
    input_params: Mapped[Dict[str, Any]] = mapped_column(JSON, nullable=False)
 | 
					    input_params: Mapped[Dict[str, Any]] = mapped_column(JSON, nullable=False)
 | 
				
			||||||
    output_results: Mapped[Dict[str, Any] | None] = mapped_column(JSON, nullable=True)
 | 
					    output_results: Mapped[Dict[str, Any] | None] = mapped_column(JSON, nullable=True)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,20 +0,0 @@
 | 
				
			||||||
from sqlalchemy import Column, Integer, String, JSON, Float, DateTime
 | 
					 | 
				
			||||||
from sqlalchemy.sql import func
 | 
					 | 
				
			||||||
from sqlalchemy.ext.declarative import declarative_base
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
Base = declarative_base()
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class Calculation(Base):
 | 
					 | 
				
			||||||
    __tablename__ = "calculations"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    id = Column(Integer, primary_key=True, index=True)
 | 
					 | 
				
			||||||
    input_params = Column(JSON)
 | 
					 | 
				
			||||||
    output_results = Column(JSON)
 | 
					 | 
				
			||||||
    timestamp = Column(DateTime(timezone=True), server_default=func.now())
 | 
					 | 
				
			||||||
    model_name = Column(String, nullable=True)
 | 
					 | 
				
			||||||
    objective_score = Column(Float, nullable=True)
 | 
					 | 
				
			||||||
    # Удалите эти строки, если они есть:
 | 
					 | 
				
			||||||
    # user_id = Column(Integer, ForeignKey("users.id"))
 | 
					 | 
				
			||||||
    # user = relationship("User", back_populates="calculations")
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
# Можно вообще удалить класс User, если он больше не нужен 
 | 
					 | 
				
			||||||
| 
						 | 
					@ -7,8 +7,8 @@ from app.services import calculation_service as service
 | 
				
			||||||
from app.db.session import get_db
 | 
					from app.db.session import get_db
 | 
				
			||||||
 | 
					
 | 
				
			||||||
router = APIRouter(
 | 
					router = APIRouter(
 | 
				
			||||||
    prefix="/calculation", # Общий префикс для эндпоинтов этого роутера
 | 
					    prefix="/calculation", 
 | 
				
			||||||
    tags=["Calculations"], # Тег для группировки в документации Swagger
 | 
					    tags=["Calculations"], 
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@router.post("/", response_model=CalculationRead, status_code=status.HTTP_201_CREATED)
 | 
					@router.post("/", response_model=CalculationRead, status_code=status.HTTP_201_CREATED)
 | 
				
			||||||
| 
						 | 
					@ -45,8 +45,6 @@ async def read_calculation(
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
    return db_calc
 | 
					    return db_calc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Определяем эндпоинт для истории до эндпоинта с ID,
 | 
					 | 
				
			||||||
# чтобы FastAPI не принял "history" за ID
 | 
					 | 
				
			||||||
@router.get("/history/", response_model=List[CalculationRead])
 | 
					@router.get("/history/", response_model=List[CalculationRead])
 | 
				
			||||||
async def read_calculation_history(
 | 
					async def read_calculation_history(
 | 
				
			||||||
    skip: int = 0,
 | 
					    skip: int = 0,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,34 +2,22 @@ from pydantic import BaseModel, ConfigDict
 | 
				
			||||||
from datetime import datetime
 | 
					from datetime import datetime
 | 
				
			||||||
from typing import Optional, Dict, Any
 | 
					from typing import Optional, Dict, Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --- Базовая схема ---
 | 
					 | 
				
			||||||
# Общие поля для расчета
 | 
					 | 
				
			||||||
class CalculationBase(BaseModel):
 | 
					class CalculationBase(BaseModel):
 | 
				
			||||||
    input_params: Dict[str, Any]
 | 
					    input_params: Dict[str, Any]
 | 
				
			||||||
    model_name: Optional[str] = None # Модель может быть выбрана сервером
 | 
					    model_name: Optional[str] = None 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --- Схема для создания (запуска) расчета ---
 | 
					 | 
				
			||||||
# Данные, которые пользователь отправляет для запуска
 | 
					 | 
				
			||||||
class CalculationCreate(CalculationBase):
 | 
					class CalculationCreate(CalculationBase):
 | 
				
			||||||
    pass # Пока совпадает с Base, но может быть расширена
 | 
					    pass 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# --- Схема для чтения ---
 | 
					 | 
				
			||||||
# Полная информация о расчете, возвращаемая API
 | 
					 | 
				
			||||||
class CalculationRead(CalculationBase):
 | 
					class CalculationRead(CalculationBase):
 | 
				
			||||||
    id: int
 | 
					    id: int
 | 
				
			||||||
    output_results: Optional[Dict[str, Any]] = None
 | 
					    output_results: Optional[Dict[str, Any]] = None
 | 
				
			||||||
    timestamp: datetime
 | 
					    timestamp: datetime
 | 
				
			||||||
    objective_score: Optional[float] = None
 | 
					    objective_score: Optional[float] = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Включаем режим ORM
 | 
					 | 
				
			||||||
    model_config = ConfigDict(from_attributes=True)
 | 
					    model_config = ConfigDict(from_attributes=True)
 | 
				
			||||||
    # В Pydantic v1 было:
 | 
					 | 
				
			||||||
    # class Config:
 | 
					 | 
				
			||||||
    #     orm_mode = True
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
# --- Опционально: Схема для обновления (если результаты добавляются позже) ---
 | 
					 | 
				
			||||||
class CalculationUpdate(BaseModel):
 | 
					class CalculationUpdate(BaseModel):
 | 
				
			||||||
    output_results: Optional[Dict[str, Any]] = None
 | 
					    output_results: Optional[Dict[str, Any]] = None
 | 
				
			||||||
    objective_score: Optional[float] = None
 | 
					    objective_score: Optional[float] = None
 | 
				
			||||||
    model_name: Optional[str] = None # Если модель определяется по результату 
 | 
					    model_name: Optional[str] = None 
 | 
				
			||||||
| 
						 | 
					@ -6,6 +6,4 @@ class Token(BaseModel):
 | 
				
			||||||
    token_type: str
 | 
					    token_type: str
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class TokenData(BaseModel):
 | 
					class TokenData(BaseModel):
 | 
				
			||||||
    username: Optional[str] = None
 | 
					    username: Optional[str] = None
 | 
				
			||||||
    # Можно использовать id пользователя, если удобнее
 | 
					 | 
				
			||||||
    # user_id: Optional[int] = None 
 | 
					 | 
				
			||||||
| 
						 | 
					@ -3,25 +3,19 @@ from typing import List, Optional, Dict, Any
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from app.models.calculation import Calculation
 | 
					from app.models.calculation import Calculation
 | 
				
			||||||
from app.schemas.calculation import CalculationCreate, CalculationUpdate
 | 
					from app.schemas.calculation import CalculationCreate, CalculationUpdate
 | 
				
			||||||
from app.fuzzy_solver import solve_cutting_problem # Импортируем асинхронную заглушку
 | 
					from app.fuzzy_solver import solve_cutting_problem 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Делаем функцию создания асинхронной
 | 
					 | 
				
			||||||
async def create_calculation(db: Session, calc_in: CalculationCreate) -> Calculation:
 | 
					async def create_calculation(db: Session, calc_in: CalculationCreate) -> Calculation:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Асинхронно создает запись о расчете, вызывает заглушку и сохраняет результат.
 | 
					    Асинхронно создает запись о расчете, вызывает заглушку и сохраняет результат.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    # 1. Вызываем асинхронную заглушку расчета
 | 
					 | 
				
			||||||
    print("Calling async solver...")
 | 
					    print("Calling async solver...")
 | 
				
			||||||
    output_results = await solve_cutting_problem(calc_in.input_params)
 | 
					    output_results = await solve_cutting_problem(calc_in.input_params)
 | 
				
			||||||
    print("Async solver finished.")
 | 
					    print("Async solver finished.")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 2. Определяем другие параметры (логика остается)
 | 
					 | 
				
			||||||
    objective_score = output_results.get("waste_percentage")
 | 
					    objective_score = output_results.get("waste_percentage")
 | 
				
			||||||
    model_name = calc_in.model_name or "default_fuzzy_model_v1"
 | 
					    model_name = calc_in.model_name or "default_fuzzy_model_v1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 3. Создаем объект модели SQLAlchemy
 | 
					 | 
				
			||||||
    # Операции с БД остаются синхронными в этом примере
 | 
					 | 
				
			||||||
    # Для полной асинхронности потребовался бы async-драйвер и AsyncSession
 | 
					 | 
				
			||||||
    print("Creating DB object...")
 | 
					    print("Creating DB object...")
 | 
				
			||||||
    db_calc = Calculation(
 | 
					    db_calc = Calculation(
 | 
				
			||||||
        input_params=calc_in.input_params,
 | 
					        input_params=calc_in.input_params,
 | 
				
			||||||
| 
						 | 
					@ -30,7 +24,6 @@ async def create_calculation(db: Session, calc_in: CalculationCreate) -> Calcula
 | 
				
			||||||
        model_name=model_name
 | 
					        model_name=model_name
 | 
				
			||||||
    )
 | 
					    )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # 4. Сохраняем в базу данных (синхронные операции)
 | 
					 | 
				
			||||||
    print("Adding to DB session...")
 | 
					    print("Adding to DB session...")
 | 
				
			||||||
    db.add(db_calc)
 | 
					    db.add(db_calc)
 | 
				
			||||||
    print("Committing DB session...")
 | 
					    print("Committing DB session...")
 | 
				
			||||||
| 
						 | 
					@ -40,8 +33,6 @@ async def create_calculation(db: Session, calc_in: CalculationCreate) -> Calcula
 | 
				
			||||||
    print("Calculation created and saved.")
 | 
					    print("Calculation created and saved.")
 | 
				
			||||||
    return db_calc
 | 
					    return db_calc
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# Функции чтения можно оставить синхронными, т.к. они быстрые
 | 
					 | 
				
			||||||
# и используют синхронную сессию
 | 
					 | 
				
			||||||
def get_calculation_by_id(db: Session, calc_id: int) -> Optional[Calculation]:
 | 
					def get_calculation_by_id(db: Session, calc_id: int) -> Optional[Calculation]:
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    Получает расчет по его ID.
 | 
					    Получает расчет по его ID.
 | 
				
			||||||
| 
						 | 
					@ -53,16 +44,3 @@ def get_calculations(db: Session, skip: int = 0, limit: int = 100) -> List[Calcu
 | 
				
			||||||
    Получает список всех расчетов с пагинацией.
 | 
					    Получает список всех расчетов с пагинацией.
 | 
				
			||||||
    """
 | 
					    """
 | 
				
			||||||
    return db.query(Calculation).offset(skip).limit(limit).all()
 | 
					    return db.query(Calculation).offset(skip).limit(limit).all()
 | 
				
			||||||
 | 
					 | 
				
			||||||
# Опционально: Функция для обновления расчета (если нужно)
 | 
					 | 
				
			||||||
# def update_calculation(db: Session, calc_id: int, calc_update: CalculationUpdate) -> Optional[Calculation]:
 | 
					 | 
				
			||||||
#     db_calc = get_calculation_by_id(db, calc_id)
 | 
					 | 
				
			||||||
#     if not db_calc:
 | 
					 | 
				
			||||||
#         return None
 | 
					 | 
				
			||||||
#     update_data = calc_update.model_dump(exclude_unset=True) # Pydantic v2
 | 
					 | 
				
			||||||
#     # update_data = calc_update.dict(exclude_unset=True) # Pydantic v1
 | 
					 | 
				
			||||||
#     for key, value in update_data.items():
 | 
					 | 
				
			||||||
#         setattr(db_calc, key, value)
 | 
					 | 
				
			||||||
#     db.commit()
 | 
					 | 
				
			||||||
#     db.refresh(db_calc)
 | 
					 | 
				
			||||||
#     return db_calc 
 | 
					 | 
				
			||||||
		Loading…
	
		Reference in New Issue