chore(pm): vendor the Aramesh/PM platform under pm/ (squash of Aramesh/PM @ 91f3271)
The PM panel (PmPanelPage -> iframe /pm/) needs the project-management platform served at /pm/ on the ERP domain. Source: org repo Aramesh/PM, branch feature/project-management-platform. Update via: git subtree pull --prefix=pm aramesh-pm feature/project-management-platform --squash
This commit is contained in:
@@ -0,0 +1,79 @@
|
||||
"""PM — Project Management operational layer. FastAPI entrypoint."""
|
||||
import asyncio
|
||||
import logging
|
||||
from contextlib import asynccontextmanager
|
||||
|
||||
from fastapi import FastAPI
|
||||
from sqlalchemy import select
|
||||
|
||||
from app.config import settings
|
||||
from app.db import SessionFactory, engine
|
||||
from app.dev_accounts import ensure_demo_accounts, ensure_demo_assignments
|
||||
from app.errors import install_error_handlers
|
||||
from app.models import Base, PMUser
|
||||
from app.routers import auth, dashboard, files, projects, qc, tasks, users
|
||||
from app.security import hash_password
|
||||
|
||||
logging.basicConfig(level=logging.INFO, format="%(asctime)s %(levelname)s %(name)s — %(message)s")
|
||||
logging.getLogger("httpx").setLevel(logging.WARNING)
|
||||
|
||||
|
||||
async def _ensure_admin() -> None:
|
||||
"""Seed the local admin user (role: project_manager) from env on first boot."""
|
||||
async with SessionFactory() as db:
|
||||
existing = await db.scalar(select(PMUser).where(PMUser.username == settings.ADMIN_USER))
|
||||
if existing is None:
|
||||
db.add(
|
||||
PMUser(
|
||||
username=settings.ADMIN_USER,
|
||||
password_hash=hash_password(settings.ADMIN_PASSWORD),
|
||||
display_name="مدیر سیستم",
|
||||
role="project_manager",
|
||||
)
|
||||
)
|
||||
await db.commit()
|
||||
logging.getLogger("pm.boot").info("seeded admin user %s", settings.ADMIN_USER)
|
||||
# dev role switcher: demo accounts for the dashboard picker
|
||||
await ensure_demo_accounts(db)
|
||||
|
||||
|
||||
@asynccontextmanager
|
||||
async def lifespan(_: FastAPI):
|
||||
if settings.DEV_ROLE_SWITCH:
|
||||
logging.getLogger("pm.boot").warning(
|
||||
"PM_DEV_ROLE_SWITCH is ON — /auth/dev-login issues tokens without a password. "
|
||||
"Set PM_DEV_ROLE_SWITCH=false for production."
|
||||
)
|
||||
async with engine.begin() as conn:
|
||||
from app.schema_sync import drop_legacy, ensure_schema
|
||||
|
||||
await drop_legacy(conn)
|
||||
await conn.run_sync(Base.metadata.create_all)
|
||||
await ensure_schema(conn)
|
||||
await _ensure_admin()
|
||||
asyncio.create_task(_init_demo_assignments())
|
||||
yield
|
||||
|
||||
|
||||
async def _init_demo_assignments() -> None:
|
||||
await asyncio.sleep(1)
|
||||
try:
|
||||
async with SessionFactory() as db:
|
||||
await ensure_demo_assignments(db)
|
||||
except Exception: # noqa: BLE001
|
||||
logging.getLogger("pm.boot").exception("demo assignment failed")
|
||||
|
||||
|
||||
app = FastAPI(title="PM — Construction Project Management Platform", version="1.0.0", lifespan=lifespan)
|
||||
|
||||
API_V1_PREFIX = "/api/v1"
|
||||
for module in (auth, users, dashboard, projects, tasks, qc, files):
|
||||
app.include_router(module.router, prefix=API_V1_PREFIX)
|
||||
|
||||
|
||||
@app.get("/health")
|
||||
async def health():
|
||||
return {"status": "ok", "service": "pm-api"}
|
||||
|
||||
|
||||
install_error_handlers(app)
|
||||
Reference in New Issue
Block a user