import os from typing import Optional import httpx from fastapi import HTTPException, status from sqlalchemy import Delete, desc, Select, select, func from sqlalchemy.orm import selectinload from src.aeros_equipment.service import save_default_equipment from src.aeros_simulation.service import save_default_simulation_node from src.auth.service import CurrentUser from src.config import WINDOWS_AEROS_BASE_URL, AEROS_BASE_URL from src.database.core import DbSession from src.database.service import search_filter_sort_paginate from .model import AerosProject from .schema import AerosProjectInput import asyncio ALLOWED_EXTENSIONS = {".aro"} MAX_FILE_SIZE = 100 * 1024 * 1024 # 100MB client = httpx.AsyncClient(timeout=300.0) async def import_aro_project(*, db_session: DbSession, aeros_project_in: AerosProjectInput): # windows_aeros_base_url = WINDOWS_AEROS_BASE_URL file = aeros_project_in.aro_file # Get filename filename_without_ext = os.path.splitext(file.filename)[0] # Get file extension file_ext = os.path.splitext(file.filename)[1].lower() # Validate file extension if file_ext not in ALLOWED_EXTENSIONS: raise HTTPException( status_code=400, detail=f"File type not allowed. Allowed: {ALLOWED_EXTENSIONS}" ) print("read file") # Read and check file size content = await file.read() if len(content) > MAX_FILE_SIZE: raise HTTPException( status_code=400, detail="File too large. Max size: 100Mb" ) # Project name hardcode # project_name = "trialapi" # Project name project_name = filename_without_ext ## save File to windows app # Output is string of file path, examole # # Example response "C/dsad/dsad.aro" try: # Reset file position since we already read it for size check # await file.seek(0) # Prepare file for upload files = { "file": (file.filename, content, file.content_type or "application/octet-stream") } print("fetch") response = await client.post( f"{WINDOWS_AEROS_BASE_URL}/upload-file", files=files ) response.raise_for_status() # Get the file path from the response upload_result = response.json() aro_path = upload_result.get("full_path") filename = upload_result.get("stored_filename").replace(".aro", "") if not aro_path: raise HTTPException( status_code=500, detail="Failed to get file path from upload response" ) except httpx.HTTPStatusError as e: raise HTTPException( status_code=e.response.status_code, detail=f"Upload failed: {e.response.text}" ) except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e) ) await asyncio.sleep(2) # aro_path = r"C:/Users/user/Documents/Aeros/sample_project.aro" aeros_project = AerosProject(project_name=filename, aro_file_path=aro_path) # find aeros record first, if not found, then create a new one stmt = select(AerosProject).order_by(desc(AerosProject.created_at)).limit(1) result = await db_session.execute(stmt) latest_project = result.scalar_one_or_none() # If aeros record found, then update it if latest_project: latest_project.project_name = filename latest_project.aro_file_path = aro_path else: # else create new aeros record db_session.add(aeros_project) await db_session.commit() # Update path to AEROS APP # Example BODy "C/dsad/dsad.aro" try: response = await client.post( f"{AEROS_BASE_URL}/api/Project/ImportAROFile", content=f'"{aro_path}"', headers={"Content-Type": "application/json"}, ) response.raise_for_status() except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e) ) await _initialize_default_project_data( db_session=db_session, project_name=filename ) async def fetch_aro_record(*, db_session: DbSession): stmt = select(AerosProject).order_by(desc(AerosProject.updated_at)).limit(1) result = await db_session.execute(stmt) found_record = result.scalar_one_or_none() return found_record async def get_project(*, db_session: DbSession): stmt = select(AerosProject).order_by(desc(AerosProject.updated_at)).limit(1) result = await db_session.execute(stmt) found_record = result.scalar_one_or_none() return found_record async def _initialize_default_project_data( *, db_session: DbSession, project_name: str ) -> None: """ Initialize default equipment and simulation nodes for a project. Args: db_session: Database session project_name: Name of the project to initialize """ try: # Save default equipment await save_default_equipment( db_session=db_session, project_name=project_name ) # # Save default simulation node # await save_default_simulation_node( # db_session=db_session, # project_name=project_name # ) await db_session.commit() except Exception as e: await db_session.rollback() raise e async def reset_project(*, db_session: DbSession): project = await fetch_aro_record(db_session=db_session) try: response = await client.post( f"{AEROS_BASE_URL}/api/Project/ImportAROFile", content=f'"{project.aro_file_path}"', headers={"Content-Type": "application/json"}, ) response.raise_for_status() except Exception as e: raise HTTPException( status_code=status.HTTP_500_INTERNAL_SERVER_ERROR, detail=str(e) ) return project.aro_file_path