from fastapi import FastAPI, File, UploadFile, Form, Depends import uvicorn import json from contextlib import asynccontextmanager from fastapi.staticfiles import StaticFiles # Add this import from PIL import Image import io import os os.makedirs("/tmp/reports", exist_ok=True) from services.measurement_service import MeasurementService from services.pdf_service import PdfService from services.persistence_service import PersistenceService from models.schemas import MeasurementMetadata from models.database import create_db_and_tables @asynccontextmanager async def lifespan(app: FastAPI): # create database and tables on startup create_db_and_tables() yield from fastapi.middleware.cors import CORSMiddleware app = FastAPI(title="Ship Draft Measurement API", lifespan=lifespan) app.add_middleware( CORSMiddleware, allow_origins=["*"], # Allows all origins allow_credentials=True, allow_methods=["*"], # Allows all methods allow_headers=["*"], # Allows all headers ) # Mount static files directory app.mount("/static", StaticFiles(directory="/tmp/reports"), name="static") # Add this line # Initialize services measurement_service = MeasurementService() pdf_service = PdfService() persistence_service = PersistenceService() @app.get("/", tags=["Health Check"]) def read_root(): """A simple endpoint to check if the API is running.""" return {"status": "API is running"} @app.post("/measure", tags=["Measurement"]) async def measure_draft( image: UploadFile = File(...), metadata_json: str = Form(...) ): """ Receives an image and metadata, performs draft measurement, generates a PDF report, and saves it. """ # 1. Read image content image_bytes = await image.read() # 2. Deserialize and validate metadata metadata_dict = json.loads(metadata_json) metadata = MeasurementMetadata(**metadata_dict) # 3. Perform measurement (using placeholder service) image_pil = Image.open(io.BytesIO(image_bytes)) measurement_results, ml_results = measurement_service.measure(image_pil) # 4. Generate PDF report pdf_report_bytes = pdf_service.create_report( image_bytes=image_bytes, metadata=metadata, results=measurement_results, ml_results=ml_results ) # 5. Persist the report report_path = persistence_service.save_to_disk(pdf_report_bytes, metadata) persistence_service.save_to_db( report_path, metadata, measurement_results.draft_measurement, measurement_results.confidence_score, image_bytes ) # Optional: Send email # persistence_service.send_by_email(report_path, "pfnfcat@gmail.com") return { "message": "Measurement complete and report generated.", "report_path": report_path, "results": measurement_results } from datetime import datetime from typing import Optional @app.get("/reports", tags=["Reports"]) def get_reports( skip: int = 0, limit: int = 10, search: Optional[str] = None, start_date: Optional[datetime] = None, end_date: Optional[datetime] = None, ): """Returns a list of all reports.""" return persistence_service.get_all_reports( skip=skip, limit=limit, search=search, start_date=start_date, end_date=end_date, ) @app.get("/reports/{report_id}", tags=["Reports"]) def get_report(report_id: int): """Returns a single report by its ID.""" report = persistence_service.get_report_by_id(report_id) if report is None: return {"error": "Report not found"} return report if __name__ == "__main__": uvicorn.run(app, host="0.0.0.0", port=8000)