Initial commit: PESCO NCR system
Complete Non-Conformance Report system replacing the PowerApps/SharePoint prototype: FastAPI + SQLAlchemy 2 (async) + Alembic + MySQL 8 backend, React 18 + Vite + TypeScript + MUI frontend, Entra ID auth (MSAL / JWKS, group-gated), Microsoft Graph delegated Mail.Send notifications (OBO), six-stage workflow state machine with server-side enforcement, atomic NCR-YYYY-NNNN numbering, attachments with camera capture, immutable field-level audit trail, admin reopen, reports + CSV export, WeasyPrint PDF traveler, Power BI reporting views + read-only DB user, documented VISUAL ERP job-lookup stub, pytest suite (26 tests), docker-compose deployment. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
57
backend/app/main.py
Normal file
57
backend/app/main.py
Normal file
@@ -0,0 +1,57 @@
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
from pathlib import Path
|
||||
|
||||
from fastapi import FastAPI
|
||||
from fastapi.middleware.cors import CORSMiddleware
|
||||
|
||||
from app.config import get_settings
|
||||
from app.routers import admin, health, jobs, lookups, ncrs, reports, users
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(app: FastAPI):
|
||||
settings = get_settings()
|
||||
logging.basicConfig(
|
||||
level=getattr(logging, settings.log_level.upper(), logging.INFO),
|
||||
format="%(asctime)s %(levelname)s %(name)s: %(message)s",
|
||||
)
|
||||
Path(settings.attachments_dir).mkdir(parents=True, exist_ok=True)
|
||||
if settings.auth_mode == "dev":
|
||||
logging.getLogger(__name__).warning(
|
||||
"AUTH_MODE=dev — authentication is BYPASSED. Never use in production."
|
||||
)
|
||||
# Fail fast on a misconfigured job-lookup provider.
|
||||
from app.services.job_lookup import get_job_lookup_service
|
||||
|
||||
get_job_lookup_service()
|
||||
yield
|
||||
|
||||
|
||||
app = FastAPI(
|
||||
title="PESCO NCR API",
|
||||
version="1.0.0",
|
||||
docs_url="/api/docs",
|
||||
openapi_url="/api/openapi.json",
|
||||
redoc_url=None,
|
||||
lifespan=lifespan,
|
||||
)
|
||||
|
||||
# In production nginx serves the SPA and proxies /api same-origin, so CORS is
|
||||
# only exercised by the Vite dev server.
|
||||
app.add_middleware(
|
||||
CORSMiddleware,
|
||||
allow_origins=["http://localhost:5173", "http://127.0.0.1:5173"],
|
||||
allow_credentials=True,
|
||||
allow_methods=["*"],
|
||||
allow_headers=["*"],
|
||||
)
|
||||
|
||||
API = "/api"
|
||||
app.include_router(health.router, prefix=API)
|
||||
app.include_router(users.router, prefix=API)
|
||||
app.include_router(lookups.router, prefix=API)
|
||||
app.include_router(jobs.router, prefix=API)
|
||||
app.include_router(ncrs.router, prefix=API)
|
||||
app.include_router(reports.router, prefix=API)
|
||||
app.include_router(admin.router, prefix=API)
|
||||
Reference in New Issue
Block a user