"""FastAPI: Excel workbook → detect VV sheets → find price inconsistencies → Excel report.""" import logging import os import uuid from pathlib import Path from fastapi import FastAPI, File, HTTPException, UploadFile from fastapi.middleware.cors import CORSMiddleware from fastapi.responses import FileResponse from fastapi.staticfiles import StaticFiles from vv_logic import analyse, write_report logging.basicConfig(level=logging.INFO) logger = logging.getLogger(__name__) app = FastAPI(title="VV Price Check") app.add_middleware(CORSMiddleware, allow_origins=["*"], allow_methods=["*"], allow_headers=["*"]) WORK_DIR = Path(os.getenv("WORK_DIR", "/tmp/vv-check")) WORK_DIR.mkdir(parents=True, exist_ok=True) jobs: dict[str, dict] = {} @app.get("/") async def root(): return FileResponse("static/index.html") @app.post("/api/check") async def check(file: UploadFile = File(...)): suffix = Path(file.filename or "").suffix.lower() if suffix not in (".xlsx", ".xlsm"): raise HTTPException(400, "Podporované formáty: .xlsx, .xlsm") job_id = str(uuid.uuid4()) job_dir = WORK_DIR / job_id job_dir.mkdir() input_path = job_dir / f"input{suffix}" input_path.write_bytes(await file.read()) logger.info("Job %s: %s (%d bytes)", job_id, file.filename, input_path.stat().st_size) try: result = analyse(input_path) except Exception as exc: logger.exception("Analysis failed") raise HTTPException(500, f"Analýza selhala: {exc}") jobs[job_id] = { "filename": file.filename, "job_dir": str(job_dir), "result": result, } return {"job_id": job_id, "result": result} @app.get("/api/report/{job_id}") async def report(job_id: str): if job_id not in jobs: raise HTTPException(404, "Úloha nenalezena") job = jobs[job_id] out_path = Path(job["job_dir"]) / "report.xlsx" write_report(job["result"], job.get("filename") or "kalkulace.xlsx", out_path) stem = Path(job["filename"]).stem if job.get("filename") else "kalkulace" return FileResponse( str(out_path), media_type="application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", filename=f"kontrola_cen_{stem}.xlsx", ) @app.get("/health") async def health(): return {"status": "ok"} app.mount("/static", StaticFiles(directory="static"), name="static")