Files
MMD 2747f9d4bb 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
2026-10-07 15:14:20 +03:30

54 lines
1.4 KiB
Python

"""PM error envelope — same contract as the ERP: {"error": {code, message, field}}."""
from fastapi import FastAPI, Request
from fastapi.responses import JSONResponse
class AppError(Exception):
status_code = 400
code = "BAD_REQUEST"
def __init__(self, message: str, field: str | None = None, code: str | None = None):
super().__init__(message)
self.message = message
self.field = field
if code:
self.code = code
@property
def body(self) -> dict:
error = {"code": self.code, "message": self.message}
if self.field is not None:
error["field"] = self.field
return {"error": error}
class AuthError(AppError):
status_code, code = 401, "UNAUTHORIZED"
class ValidationError(AppError):
status_code, code = 400, "VALIDATION_ERROR"
class ForbiddenError(AppError):
status_code, code = 403, "FORBIDDEN"
class NotFoundError(AppError):
status_code, code = 404, "NOT_FOUND"
class ConflictError(AppError):
status_code, code = 409, "CONFLICT"
class UpstreamError(AppError):
"""Upstream service unreachable / errored."""
status_code, code = 503, "UPSTREAM_UNAVAILABLE"
def install_error_handlers(app: FastAPI) -> None:
@app.exception_handler(AppError)
async def _app_error(_: Request, exc: AppError) -> JSONResponse:
return JSONResponse(status_code=exc.status_code, content=exc.body)