"""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,
)