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:
449
plugins/wordpress/handlers/orders.py
Normal file
449
plugins/wordpress/handlers/orders.py
Normal file
@@ -0,0 +1,449 @@
|
||||
"""Orders Handler - manages WooCommerce orders"""
|
||||
|
||||
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 [
|
||||
{
|
||||
"name": "list_orders",
|
||||
"method_name": "list_orders",
|
||||
"description": "List WooCommerce orders. Returns paginated order list with customer details, totals, and status.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"per_page": {
|
||||
"type": "integer",
|
||||
"description": "Number of orders per page (1-100)",
|
||||
"default": 10,
|
||||
"minimum": 1,
|
||||
"maximum": 100,
|
||||
},
|
||||
"page": {
|
||||
"type": "integer",
|
||||
"description": "Page number",
|
||||
"default": 1,
|
||||
"minimum": 1,
|
||||
},
|
||||
"status": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "string",
|
||||
"enum": [
|
||||
"any",
|
||||
"pending",
|
||||
"processing",
|
||||
"on-hold",
|
||||
"completed",
|
||||
"cancelled",
|
||||
"refunded",
|
||||
"failed",
|
||||
"trash",
|
||||
],
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"description": "Filter by order status (optional)",
|
||||
},
|
||||
"customer": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"description": "Filter by customer ID",
|
||||
},
|
||||
"after": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Filter orders after this date (ISO 8601 format)",
|
||||
},
|
||||
"before": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Filter orders before this date (ISO 8601 format)",
|
||||
},
|
||||
},
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "get_order",
|
||||
"method_name": "get_order",
|
||||
"description": "Get detailed information about a specific WooCommerce order. Returns full order details including line items, totals, billing, and shipping.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "integer",
|
||||
"description": "Order ID to retrieve",
|
||||
"minimum": 1,
|
||||
}
|
||||
},
|
||||
"required": ["order_id"],
|
||||
},
|
||||
"scope": "read",
|
||||
},
|
||||
{
|
||||
"name": "update_order_status",
|
||||
"method_name": "update_order_status",
|
||||
"description": "Update WooCommerce order status. Change order status to pending, processing, completed, etc.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "integer",
|
||||
"description": "Order ID to update",
|
||||
"minimum": 1,
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "New order status",
|
||||
"enum": [
|
||||
"pending",
|
||||
"processing",
|
||||
"on-hold",
|
||||
"completed",
|
||||
"cancelled",
|
||||
"refunded",
|
||||
"failed",
|
||||
],
|
||||
},
|
||||
},
|
||||
"required": ["order_id", "status"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "create_order",
|
||||
"method_name": "create_order",
|
||||
"description": "Create a new WooCommerce order. Supports line items, billing, shipping, and payment method configuration.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"customer_id": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"description": "Customer ID (optional)",
|
||||
},
|
||||
"line_items": {
|
||||
"anyOf": [
|
||||
{
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"product_id": {
|
||||
"type": "integer",
|
||||
"description": "Product ID",
|
||||
},
|
||||
"quantity": {
|
||||
"type": "integer",
|
||||
"description": "Quantity",
|
||||
"minimum": 1,
|
||||
},
|
||||
"variation_id": {
|
||||
"anyOf": [{"type": "integer"}, {"type": "null"}],
|
||||
"description": "Variation ID (for variable products)",
|
||||
},
|
||||
},
|
||||
"required": ["product_id", "quantity"],
|
||||
},
|
||||
},
|
||||
{"type": "null"},
|
||||
],
|
||||
"description": "Order line items with product IDs and quantities",
|
||||
},
|
||||
"billing": {
|
||||
"anyOf": [{"type": "object"}, {"type": "null"}],
|
||||
"description": "Billing address object",
|
||||
},
|
||||
"shipping": {
|
||||
"anyOf": [{"type": "object"}, {"type": "null"}],
|
||||
"description": "Shipping address object",
|
||||
},
|
||||
"payment_method": {
|
||||
"anyOf": [{"type": "string"}, {"type": "null"}],
|
||||
"description": "Payment method ID (e.g., 'bacs', 'cod', 'paypal')",
|
||||
},
|
||||
"status": {
|
||||
"type": "string",
|
||||
"description": "Order status",
|
||||
"enum": ["pending", "processing", "on-hold", "completed"],
|
||||
"default": "pending",
|
||||
},
|
||||
},
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
{
|
||||
"name": "delete_order",
|
||||
"method_name": "delete_order",
|
||||
"description": "Delete or trash a WooCommerce order. Can permanently delete or move to trash.",
|
||||
"schema": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"order_id": {
|
||||
"type": "integer",
|
||||
"description": "Order ID to delete",
|
||||
"minimum": 1,
|
||||
},
|
||||
"force": {
|
||||
"type": "boolean",
|
||||
"description": "Permanently delete (true) or move to trash (false)",
|
||||
"default": False,
|
||||
},
|
||||
},
|
||||
"required": ["order_id"],
|
||||
},
|
||||
"scope": "write",
|
||||
},
|
||||
]
|
||||
|
||||
class OrdersHandler:
|
||||
"""Handle WooCommerce order-related operations"""
|
||||
|
||||
def __init__(self, client: WordPressClient):
|
||||
"""
|
||||
Initialize orders handler.
|
||||
|
||||
Args:
|
||||
client: WordPress API client instance
|
||||
"""
|
||||
self.client = client
|
||||
|
||||
async def list_orders(
|
||||
self,
|
||||
per_page: int = 10,
|
||||
page: int = 1,
|
||||
status: str | None = None,
|
||||
customer: int | None = None,
|
||||
after: str | None = None,
|
||||
before: str | None = None,
|
||||
) -> str:
|
||||
"""
|
||||
List WooCommerce orders with filters.
|
||||
|
||||
Args:
|
||||
per_page: Number of orders per page (1-100)
|
||||
page: Page number
|
||||
status: Filter by order status (any, pending, processing, on-hold, completed, cancelled, refunded, failed, trash)
|
||||
customer: Filter by customer ID
|
||||
after: Filter orders after this date (ISO 8601 format)
|
||||
before: Filter orders before this date (ISO 8601 format)
|
||||
|
||||
Returns:
|
||||
JSON string with orders list
|
||||
"""
|
||||
try:
|
||||
# Build query parameters
|
||||
params = {"per_page": per_page, "page": page}
|
||||
|
||||
# Add optional filters
|
||||
if status:
|
||||
params["status"] = status
|
||||
if customer is not None:
|
||||
params["customer"] = customer
|
||||
if after:
|
||||
params["after"] = after
|
||||
if before:
|
||||
params["before"] = before
|
||||
|
||||
# Make request to WooCommerce API
|
||||
orders = await self.client.get("orders", params=params, use_woocommerce=True)
|
||||
|
||||
# Format response
|
||||
result = {
|
||||
"total": len(orders),
|
||||
"page": page,
|
||||
"per_page": per_page,
|
||||
"orders": [
|
||||
{
|
||||
"id": order["id"],
|
||||
"number": order["number"],
|
||||
"status": order["status"],
|
||||
"date_created": order["date_created"],
|
||||
"date_modified": order.get("date_modified", ""),
|
||||
"total": order["total"],
|
||||
"currency": order["currency"],
|
||||
"customer_id": order["customer_id"],
|
||||
"billing": {
|
||||
"first_name": order["billing"].get("first_name", ""),
|
||||
"last_name": order["billing"].get("last_name", ""),
|
||||
"email": order["billing"].get("email", ""),
|
||||
},
|
||||
"line_items_count": len(order.get("line_items", [])),
|
||||
"payment_method_title": order.get("payment_method_title", ""),
|
||||
"transaction_id": order.get("transaction_id", ""),
|
||||
}
|
||||
for order in orders
|
||||
],
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to list orders: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def get_order(self, order_id: int) -> str:
|
||||
"""
|
||||
Get detailed information about a specific order.
|
||||
|
||||
Args:
|
||||
order_id: Order ID to retrieve
|
||||
|
||||
Returns:
|
||||
JSON string with order data
|
||||
"""
|
||||
try:
|
||||
order = await self.client.get(f"orders/{order_id}", use_woocommerce=True)
|
||||
|
||||
# Format detailed response
|
||||
result = {
|
||||
"id": order["id"],
|
||||
"number": order["number"],
|
||||
"status": order["status"],
|
||||
"currency": order["currency"],
|
||||
"date_created": order["date_created"],
|
||||
"date_modified": order.get("date_modified", ""),
|
||||
"discount_total": order["discount_total"],
|
||||
"shipping_total": order["shipping_total"],
|
||||
"total": order["total"],
|
||||
"total_tax": order["total_tax"],
|
||||
"customer_id": order["customer_id"],
|
||||
"customer_note": order.get("customer_note", ""),
|
||||
"billing": order["billing"],
|
||||
"shipping": order["shipping"],
|
||||
"payment_method": order["payment_method"],
|
||||
"payment_method_title": order.get("payment_method_title", ""),
|
||||
"transaction_id": order.get("transaction_id", ""),
|
||||
"line_items": [
|
||||
{
|
||||
"id": item["id"],
|
||||
"name": item["name"],
|
||||
"product_id": item["product_id"],
|
||||
"quantity": item["quantity"],
|
||||
"subtotal": item["subtotal"],
|
||||
"total": item["total"],
|
||||
"sku": item.get("sku", ""),
|
||||
}
|
||||
for item in order.get("line_items", [])
|
||||
],
|
||||
"shipping_lines": order.get("shipping_lines", []),
|
||||
"fee_lines": order.get("fee_lines", []),
|
||||
"coupon_lines": order.get("coupon_lines", []),
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to get order {order_id}: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def update_order_status(self, order_id: int, status: str) -> str:
|
||||
"""
|
||||
Update order status.
|
||||
|
||||
Args:
|
||||
order_id: Order ID to update
|
||||
status: New status (pending, processing, on-hold, completed, cancelled, refunded, failed)
|
||||
|
||||
Returns:
|
||||
JSON string with updated order data
|
||||
"""
|
||||
try:
|
||||
data = {"status": status}
|
||||
|
||||
order = await self.client.put(
|
||||
f"orders/{order_id}", json_data=data, use_woocommerce=True
|
||||
)
|
||||
|
||||
result = {
|
||||
"id": order["id"],
|
||||
"number": order["number"],
|
||||
"status": order["status"],
|
||||
"message": f"Order #{order['number']} status updated to '{status}'",
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to update order {order_id} status: {str(e)}"},
|
||||
indent=2,
|
||||
)
|
||||
|
||||
async def create_order(
|
||||
self,
|
||||
customer_id: int | None = None,
|
||||
line_items: list[dict] | None = None,
|
||||
billing: dict | None = None,
|
||||
shipping: dict | None = None,
|
||||
payment_method: str | None = None,
|
||||
status: str = "pending",
|
||||
) -> str:
|
||||
"""
|
||||
Create a new order.
|
||||
|
||||
Args:
|
||||
customer_id: Customer ID (optional)
|
||||
line_items: List of line items [{"product_id": 123, "quantity": 1}]
|
||||
billing: Billing address dictionary
|
||||
shipping: Shipping address dictionary
|
||||
payment_method: Payment method ID (e.g., 'bacs', 'cod', 'paypal')
|
||||
status: Order status (default: pending)
|
||||
|
||||
Returns:
|
||||
JSON string with created order data
|
||||
"""
|
||||
try:
|
||||
data = {"status": status}
|
||||
|
||||
if customer_id is not None:
|
||||
data["customer_id"] = customer_id
|
||||
if line_items:
|
||||
data["line_items"] = line_items
|
||||
if billing:
|
||||
data["billing"] = billing
|
||||
if shipping:
|
||||
data["shipping"] = shipping
|
||||
if payment_method:
|
||||
data["payment_method"] = payment_method
|
||||
|
||||
order = await self.client.post("orders", json_data=data, use_woocommerce=True)
|
||||
|
||||
result = {
|
||||
"id": order["id"],
|
||||
"number": order["number"],
|
||||
"status": order["status"],
|
||||
"total": order["total"],
|
||||
"currency": order["currency"],
|
||||
"message": f"Order #{order['number']} created successfully with ID {order['id']}",
|
||||
}
|
||||
|
||||
return json.dumps(result, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to create order: {str(e)}"}, indent=2
|
||||
)
|
||||
|
||||
async def delete_order(self, order_id: int, force: bool = False) -> str:
|
||||
"""
|
||||
Delete or trash an order.
|
||||
|
||||
Args:
|
||||
order_id: Order ID to delete
|
||||
force: Permanently delete (True) or move to trash (False)
|
||||
|
||||
Returns:
|
||||
JSON string with deletion result
|
||||
"""
|
||||
try:
|
||||
params = {"force": "true" if force else "false"}
|
||||
result = await self.client.delete(
|
||||
f"orders/{order_id}", params=params, use_woocommerce=True
|
||||
)
|
||||
|
||||
message = f"Order {order_id} {'permanently deleted' if force else 'moved to trash'}"
|
||||
return json.dumps({"success": True, "message": message, "result": result}, indent=2)
|
||||
except Exception as e:
|
||||
return json.dumps(
|
||||
{"error": str(e), "message": f"Failed to delete order {order_id}: {str(e)}"},
|
||||
indent=2,
|
||||
)
|
||||
Reference in New Issue
Block a user