Files
AiTool/backend/app/main.py
2026-03-18 17:01:10 +08:00

97 lines
3.1 KiB
Python

import os
from pathlib import Path
from typing import List
from fastapi import FastAPI
from fastapi.middleware.cors import CORSMiddleware
from fastapi.staticfiles import StaticFiles
from backend.app.routers import (
customers,
projects,
finance,
settings,
ai_settings,
email_configs,
cloud_docs,
cloud_doc_config,
portal_links,
)
from backend.app.db import Base, engine
from backend.app import models # noqa: F401 - ensure models are imported
def create_app() -> FastAPI:
app = FastAPI(
title="Ops-Core",
description="Monolithic automation & business ops platform",
version="0.1.0",
)
# Ensure database tables exist (especially when running in Docker)
@app.on_event("startup")
def on_startup() -> None:
Base.metadata.create_all(bind=engine)
# Lightweight schema migrations for SQLite (add columns if missing)
try:
from sqlalchemy import text
with engine.connect() as conn:
# finance_records: amount, billing_date
r = conn.execute(text("PRAGMA table_info(finance_records)"))
cols = [row[1] for row in r]
if "amount" not in cols:
conn.execute(text("ALTER TABLE finance_records ADD COLUMN amount NUMERIC(12,2)"))
if "billing_date" not in cols:
conn.execute(text("ALTER TABLE finance_records ADD COLUMN billing_date DATE"))
if "tags" not in cols:
conn.execute(text("ALTER TABLE finance_records ADD COLUMN tags VARCHAR(512)"))
if "meta_json" not in cols:
conn.execute(text("ALTER TABLE finance_records ADD COLUMN meta_json TEXT"))
# customers: tags
r = conn.execute(text("PRAGMA table_info(customers)"))
cols = [row[1] for row in r]
if "tags" not in cols:
conn.execute(text("ALTER TABLE customers ADD COLUMN tags VARCHAR(512)"))
conn.commit()
except Exception:
pass
# CORS
raw_origins = os.getenv("CORS_ORIGINS")
if raw_origins:
origins: List[str] = [o.strip() for o in raw_origins.split(",") if o.strip()]
else:
origins = ["*"]
app.add_middleware(
CORSMiddleware,
allow_origins=origins,
allow_credentials=True,
allow_methods=["*"],
allow_headers=["*"],
)
# Routers
app.include_router(customers.router)
app.include_router(projects.router)
app.include_router(finance.router)
app.include_router(settings.router)
app.include_router(ai_settings.router)
app.include_router(email_configs.router)
app.include_router(cloud_docs.router)
app.include_router(cloud_doc_config.router)
app.include_router(portal_links.router)
# Static data mount (for quotes, contracts, finance archives, etc.)
data_dir = Path("data")
data_dir.mkdir(parents=True, exist_ok=True)
app.mount("/data", StaticFiles(directory=str(data_dir)), name="data")
return app
app = create_app()