Initial commit: MCP Hub Community Edition v3.0.0
Community edition generated from private repo via sync pipeline. Includes 9 plugins (WordPress, WooCommerce, WP Advanced, Gitea, n8n, Supabase, OpenPanel, Appwrite, Directus) with ~587 tools. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
299
plugins/wordpress/handlers/reports.py
Normal file
299
plugins/wordpress/handlers/reports.py
Normal file
@@ -0,0 +1,299 @@
|
||||
"""Reports Handler - manages WooCommerce reporting and analytics"""
|
||||
|
||||
import json
|
||||
from typing import Any
|
||||
|
||||
from plugins.wordpress.client import WordPressClient
|
||||
|
||||
def get_tool_specifications() -> list[dict[str, Any]]:
|
||||
"""Return tool specifications for ToolGenerator"""
|
||||
return [
|
||||
# === WOOCOMMERCE REPORTS ===
|
||||
{
|
||||
"name": "get_sales_report",
|
||||
"method_name": "get_sales_report",
|
||||
"description": "Get WooCommerce sales report. Returns sales data with totals and date ranges. Note: WooCommerce v3 API has limited reporting capabilities.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"period": {
|
||||
"type": "string",
|
||||
"description": "Report period (week, month, last_month, year)",
|
||||
"enum": ["week", "month", "last_month", "year"],
|
||||
"default": "week",
|
||||
},
|
||||
"date_min": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Start date for report (ISO 8601 format, e.g., '2024-01-01')",
|
||||
},
|
||||
"date_max": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "End date for report (ISO 8601 format, e.g., '2024-12-31')",
|
||||
},
|
||||
},
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_top_sellers",
|
||||
"method_name": "get_top_sellers",
|
||||
"description": "Get top selling products report. Returns products with highest sales quantities.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"period": {
|
||||
"type": "string",
|
||||
"description": "Report period (week, month, last_month, year)",
|
||||
"enum": ["week", "month", "last_month", "year"],
|
||||
"default": "week",
|
||||
},
|
||||
"date_min": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Start date for report (ISO 8601 format)",
|
||||
},
|
||||
"date_max": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "End date for report (ISO 8601 format)",
|
||||
},
|
||||
},
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_customer_report",
|
||||
"method_name": "get_customer_report",
|
||||
"description": "Get customer statistics report. Returns customer count and spending data. Falls back to customer list if reports endpoint unavailable.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"period": {
|
||||
"type": "string",
|
||||
"description": "Report period (week, month, last_month, year)",
|
||||
"enum": ["week", "month", "last_month", "year"],
|
||||
"default": "week",
|
||||
},
|
||||
"date_min": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Start date for report (ISO 8601 format)",
|
||||
},
|
||||
"date_max": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "End date for report (ISO 8601 format)",
|
||||
},
|
||||
},
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
]
|
||||
|
||||
class ReportsHandler:
|
||||
"""Handle WooCommerce reporting operations"""
|
||||
|
||||
def __init__(self, client: WordPressClient):
|
||||
"""
|
||||
Initialize reports handler.
|
||||
|
||||
Args:
|
||||
client: WordPress API client instance
|
||||
"""
|
||||
self.client = client
|
||||
|
||||
# === WOOCOMMERCE REPORTS ===
|
||||
|
||||
async def get_sales_report(
|
||||
self, period: str = "week", date_min: str | None = None, date_max: str | None = None
|
||||
) -> str:
|
||||
"""
|
||||
Get WooCommerce sales report.
|
||||
|
||||
Args:
|
||||
period: Report period (week, month, last_month, year)
|
||||
date_min: Start date for report (ISO 8601 format, e.g., '2024-01-01')
|
||||
date_max: End date for report (ISO 8601 format, e.g., '2024-12-31')
|
||||
|
||||
Returns:
|
||||
JSON string with sales report data
|
||||
|
||||
Note:
|
||||
WooCommerce v3 API has limited reporting capabilities.
|
||||
For advanced analytics, use WooCommerce Analytics extension.
|
||||
"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
if date_min:
|
||||
params["date_min"] = date_min
|
||||
if date_max:
|
||||
params["date_max"] = date_max
|
||||
|
||||
report_data = await self.client.get(
|
||||
"reports/sales", params=params, use_woocommerce=True
|
||||
)
|
||||
|
||||
# Format the response based on what the API returns
|
||||
result = {
|
||||
"period": period,
|
||||
"sales_data": report_data if isinstance(report_data, list) else [report_data],
|
||||
"note": "WooCommerce v3 API has limited reporting. For advanced analytics, use WooCommerce Analytics extension.",
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
# Check if reports endpoint is not available
|
||||
if "404" in error_msg or "not found" in error_msg.lower():
|
||||
return json.dumps(
|
||||
{
|
||||
"error": "Sales reports endpoint not available",
|
||||
"message": "WooCommerce v3 API has limited reporting capabilities. Consider using WooCommerce Analytics or custom queries.",
|
||||
"details": error_msg,
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to get sales report: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def get_top_sellers(
|
||||
self, period: str = "week", date_min: str | None = None, date_max: str | None = None
|
||||
) -> str:
|
||||
"""
|
||||
Get top selling products report.
|
||||
|
||||
Args:
|
||||
period: Report period (week, month, last_month, year)
|
||||
date_min: Start date for report (ISO 8601 format)
|
||||
date_max: End date for report (ISO 8601 format)
|
||||
|
||||
Returns:
|
||||
JSON string with top sellers data
|
||||
"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
if date_min:
|
||||
params["date_min"] = date_min
|
||||
if date_max:
|
||||
params["date_max"] = date_max
|
||||
|
||||
top_sellers = await self.client.get(
|
||||
"reports/top_sellers", params=params, use_woocommerce=True
|
||||
)
|
||||
|
||||
result = {
|
||||
"period": period,
|
||||
"total_products": len(top_sellers) if isinstance(top_sellers, list) else 0,
|
||||
"top_sellers": [
|
||||
{
|
||||
"product_id": item.get("product_id"),
|
||||
"title": item.get("title"),
|
||||
"quantity": item.get("quantity", 0),
|
||||
}
|
||||
for item in (top_sellers if isinstance(top_sellers, list) else [])
|
||||
],
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
error_msg = str(e)
|
||||
if "404" in error_msg or "not found" in error_msg.lower():
|
||||
return json.dumps(
|
||||
{
|
||||
"error": "Top sellers endpoint not available",
|
||||
"message": "WooCommerce v3 API has limited reporting capabilities.",
|
||||
"details": error_msg,
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to get top sellers: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def get_customer_report(
|
||||
self, period: str = "week", date_min: str | None = None, date_max: str | None = None
|
||||
) -> str:
|
||||
"""
|
||||
Get customer statistics report.
|
||||
|
||||
Args:
|
||||
period: Report period (week, month, last_month, year)
|
||||
date_min: Start date for report (ISO 8601 format)
|
||||
date_max: End date for report (ISO 8601 format)
|
||||
|
||||
Returns:
|
||||
JSON string with customer report data
|
||||
|
||||
Note:
|
||||
Falls back to customer list endpoint if reports endpoint is unavailable.
|
||||
"""
|
||||
try:
|
||||
params = {"period": period}
|
||||
if date_min:
|
||||
params["date_min"] = date_min
|
||||
if date_max:
|
||||
params["date_max"] = date_max
|
||||
|
||||
try:
|
||||
customer_data = await self.client.get(
|
||||
"reports/customers", params=params, use_woocommerce=True
|
||||
)
|
||||
|
||||
result = {
|
||||
"period": period,
|
||||
"customer_data": (
|
||||
customer_data if isinstance(customer_data, list) else [customer_data]
|
||||
),
|
||||
"note": "Customer reporting may be limited in WooCommerce v3 API.",
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as report_error:
|
||||
# Check if it's a 404 error - use fallback
|
||||
if "404" in str(report_error) or "not found" in str(report_error).lower():
|
||||
return await self._get_customer_report_fallback()
|
||||
raise report_error
|
||||
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to get customer report: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def _get_customer_report_fallback(self) -> str:
|
||||
"""
|
||||
Fallback method when customer reports endpoint is not available.
|
||||
|
||||
Uses the customers list endpoint to generate basic statistics.
|
||||
|
||||
Returns:
|
||||
JSON string with basic customer statistics
|
||||
"""
|
||||
try:
|
||||
# Use customers list to generate basic stats
|
||||
customers = await self.client.get(
|
||||
"customers", params={"per_page": 100}, use_woocommerce=True
|
||||
)
|
||||
|
||||
# Calculate basic stats
|
||||
total_customers = len(customers) if isinstance(customers, list) else 0
|
||||
total_spent = (
|
||||
sum(float(c.get("total_spent", 0)) for c in customers)
|
||||
if isinstance(customers, list)
|
||||
else 0
|
||||
)
|
||||
avg_spent = total_spent / total_customers if total_customers > 0 else 0
|
||||
|
||||
result = {
|
||||
"total_customers": total_customers,
|
||||
"total_spent": f"{total_spent:.2f}",
|
||||
"average_spent_per_customer": f"{avg_spent:.2f}",
|
||||
"note": "Generated from customer list (fallback method). For detailed analytics, use WooCommerce Analytics.",
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{
|
||||
"error": str(e),
|
||||
"message": "Customer report and fallback both unavailable",
|
||||
"details": str(e),
|
||||
},
|
||||
indent=2,
|
||||
)
|
||||
Reference in New Issue
Block a user