solventum-image-metadata/backend/app/api/import_api.py
SamoilenkoVadym d5aaec5d37 fix(backend): rename import.py to import_api.py (reserved keyword)
- Rename app/api/import.py to import_api.py
- Update imports in main.py
- Fixes SyntaxError: 'import' is a reserved keyword in Python

Co-Authored-By: Claude Sonnet 4.5 (1M context) <noreply@anthropic.com>
2026-02-09 14:41:41 +00:00

187 lines
5.6 KiB
Python

"""
Import API Endpoints
Handles CSV/Excel/JSON import with column mapping.
"""
from fastapi import APIRouter, UploadFile, File, Depends, HTTPException, Request, status
from sqlalchemy.ext.asyncio import AsyncSession
from pathlib import Path
import secrets
from app.core.auth import get_current_user_id
from app.core.database import get_db, AuditLogRepository
from app.core.redis_client import RedisSessionStore
from app.services.file_service import get_file_service, FileService
from app.processors.metadata_importer import MetadataImporter
from app.models.file import (
ImportFileResponse,
ImportMappingConfig,
ExcelSheetPreviewRequest
)
router = APIRouter()
@router.post("/file", response_model=ImportFileResponse)
async def upload_import_file(
import_file: UploadFile = File(...),
request: Request = None,
user_id: int = Depends(get_current_user_id),
db: AsyncSession = Depends(get_db),
file_service: FileService = Depends(get_file_service)
):
"""
Upload CSV/Excel/JSON file for metadata import.
"""
# Save import file
file_info = await file_service.save_upload(import_file, user_id)
# Detect file type
file_ext = Path(file_info["filename"]).suffix.lower()
import_type = file_ext.replace('.', '') # csv, xlsx, json
# Preview file structure
importer = MetadataImporter()
try:
columns, sample_data, suggestions = importer.preview_file_structure(file_info["filepath"])
# For Excel files, get sheet names
sheet_names = None
if import_type == 'xlsx':
import openpyxl
wb = openpyxl.load_workbook(file_info["filepath"])
sheet_names = wb.sheetnames
# Create import session in Redis
redis: RedisSessionStore = request.app.state.redis
import_session_id = await redis.create_import_session(
user_id=user_id,
import_type=import_type,
filename=file_info["filename"],
filepath=file_info["filepath"]
)
# Log action
await AuditLogRepository.log_action(
db,
user_id=user_id,
action="import_upload",
details=f"Uploaded {import_type} import file: {file_info['filename']}"
)
return ImportFileResponse(
success=True,
import_session_id=import_session_id,
filename=file_info["filename"],
import_type=import_type,
columns=columns,
sheet_names=sheet_names,
sample_data=sample_data[:5] if sample_data else None, # First 5 rows
row_count=len(sample_data) if sample_data else 0
)
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Failed to parse import file: {str(e)}"
)
@router.post("/excel/preview")
async def preview_excel_sheet(
preview_request: ExcelSheetPreviewRequest,
request: Request,
user_id: int = Depends(get_current_user_id)
):
"""
Preview specific Excel sheet.
"""
# Get import session
redis: RedisSessionStore = request.app.state.redis
session_data = await redis.get_import_session(preview_request.excel_session_id)
if not session_data or session_data.get("user_id") != user_id:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Import session not found"
)
# Preview sheet
importer = MetadataImporter()
try:
import pandas as pd
df = pd.read_excel(session_data["filepath"], sheet_name=preview_request.sheet_name)
return {
"success": True,
"columns": df.columns.tolist(),
"sample_data": df.head(5).to_dict('records'),
"row_count": len(df)
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Failed to preview sheet: {str(e)}"
)
@router.post("/configure")
async def configure_import_mapping(
mapping_config: ImportMappingConfig,
request: Request,
user_id: int = Depends(get_current_user_id),
db: AsyncSession = Depends(get_db)
):
"""
Configure column mapping for import file.
"""
# Get import session
redis: RedisSessionStore = request.app.state.redis
session_data = await redis.get_import_session(mapping_config.import_session_id)
if not session_data or session_data.get("user_id") != user_id:
raise HTTPException(
status_code=status.HTTP_404_NOT_FOUND,
detail="Import session not found"
)
# Build column mapping dict
column_mapping = {
m.source_column: m.target_field
for m in mapping_config.column_mappings
}
# Import metadata with mapping
importer = MetadataImporter()
try:
metadata_map = importer.import_with_mapping(
session_data["filepath"],
column_mapping,
sheet_name=mapping_config.sheet_name
)
# Store metadata in session
await redis.update_import_metadata(
mapping_config.import_session_id,
metadata_map
)
# Log action
await AuditLogRepository.log_action(
db,
user_id=user_id,
action="import_configure",
details=f"Configured import mapping: {len(metadata_map)} records"
)
return {
"success": True,
"message": f"Import configured with {len(metadata_map)} records"
}
except Exception as e:
raise HTTPException(
status_code=status.HTTP_400_BAD_REQUEST,
detail=f"Failed to configure import: {str(e)}"
)