ppm_status_report_generate
Generate a project status report with auto-populated RAG, budget, risks, and milestones, created as a draft.
Instructions
Run the Status Report wizard for a project.
The wizard auto-populates RAG, budget, risks, milestones from project data
and creates a ppm.status.report in draft state.
Args:
project_id: project.project id to report on.
period: free-text period label (e.g. 'April 2026'); defaults to current month.
commentary: optional commentary field.
Returns: dict with the created status report id and summary fields.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| project_id | Yes | ||
| period | No | ||
| commentary | No |
Output Schema
| Name | Required | Description | Default |
|---|---|---|---|
No arguments | |||
Implementation Reference
- src/qod_ppm_mcp/server.py:84-127 (handler)The handler function for the ppm_status_report_generate tool. It creates a ppm.status.report.wizard record with project_id (and optional period/commentary), calls the wizard's action_create_report method, resolves the resulting report_id (with fallback search), and returns the status report's summary fields.
@mcp.tool() def ppm_status_report_generate( project_id: int, period: str | None = None, commentary: str | None = None, ) -> dict[str, Any]: """Run the Status Report wizard for a project. The wizard auto-populates RAG, budget, risks, milestones from project data and creates a `ppm.status.report` in draft state. Args: project_id: `project.project` id to report on. period: free-text period label (e.g. 'April 2026'); defaults to current month. commentary: optional commentary field. Returns: dict with the created status report id and summary fields. """ vals: dict[str, Any] = {"project_id": project_id} if period: vals["period"] = period if commentary: vals["commentary"] = commentary wizard_id = client().execute_kw("ppm.status.report.wizard", "create", [vals]) result = client().call_action("ppm.status.report.wizard", "action_create_report", [wizard_id]) report_id = (result or {}).get("res_id") if isinstance(result, dict) else None if not report_id: # Fallback: most recently-created report for this project. rows = client().search_read( "ppm.status.report", [("project_id", "=", project_id)], ["id"], limit=1, order="id desc", ) if not rows: raise RuntimeError("Wizard did not produce a status report") report_id = rows[0]["id"] return _read_state( "ppm.status.report", report_id, ["name", "state", "period", "project_id", "rag_overall"], ) - src/qod_ppm_mcp/server.py:84-85 (registration)The tool is registered via the @mcp.tool() decorator on FastMCP instance 'mcp' (line 19).
@mcp.tool() def ppm_status_report_generate( - src/qod_ppm_mcp/server.py:30-34 (helper)Helper function _read_state used by the handler to read and return fields of the created status report.
def _read_state(model: str, rec_id: int, fields: list[str]) -> dict[str, Any]: rows = client().read(model, [rec_id], fields) if not rows: raise ValueError(f"{model} id={rec_id} not found") return rows[0] - src/qod_ppm_mcp/server.py:23-27 (helper)Helper function that provides the OdooClient instance used by the handler to execute Odoo RPC calls.
def client() -> OdooClient: global _client if _client is None: _client = OdooClient.from_env() return _client