diff --git a/services/integrations/app/main.py b/services/integrations/app/main.py index 225f981..bd9ee94 100644 --- a/services/integrations/app/main.py +++ b/services/integrations/app/main.py @@ -1,6 +1,6 @@ from fastapi import FastAPI from fastapi.middleware.cors import CORSMiddleware -from app.routers import odoo_router, sync_router +from app.routers import odoo_router, sync_router, webhooks_router app = FastAPI(title="WhatsApp Central - Integrations Service") @@ -14,6 +14,7 @@ app.add_middleware( app.include_router(odoo_router) app.include_router(sync_router) +app.include_router(webhooks_router) @app.get("/health") diff --git a/services/integrations/app/routers/__init__.py b/services/integrations/app/routers/__init__.py index 8d7a2d6..9cf706c 100644 --- a/services/integrations/app/routers/__init__.py +++ b/services/integrations/app/routers/__init__.py @@ -1,4 +1,5 @@ from app.routers.odoo import router as odoo_router from app.routers.sync import router as sync_router +from app.routers.webhooks import router as webhooks_router -__all__ = ["odoo_router", "sync_router"] +__all__ = ["odoo_router", "sync_router", "webhooks_router"] diff --git a/services/integrations/app/routers/webhooks.py b/services/integrations/app/routers/webhooks.py new file mode 100644 index 0000000..7138d9f --- /dev/null +++ b/services/integrations/app/routers/webhooks.py @@ -0,0 +1,150 @@ +from fastapi import APIRouter, HTTPException, Header, Request +from pydantic import BaseModel +from typing import Optional, Dict, Any +import httpx +import hmac +import hashlib + +from app.config import get_settings + +router = APIRouter(prefix="/api/webhooks", tags=["webhooks"]) +settings = get_settings() + + +class OdooWebhookPayload(BaseModel): + model: str + action: str + record_id: int + values: Dict[str, Any] = {} + old_values: Dict[str, Any] = {} + + +@router.post("/odoo") +async def handle_odoo_webhook(payload: OdooWebhookPayload): + """ + Handle webhooks from Odoo. + Odoo sends events when records are created/updated/deleted. + """ + handlers = { + "sale.order": handle_sale_order_event, + "stock.picking": handle_stock_picking_event, + "account.move": handle_invoice_event, + } + + handler = handlers.get(payload.model) + if handler: + await handler(payload) + + return {"status": "received"} + + +async def handle_sale_order_event(payload: OdooWebhookPayload): + """Handle sale order events""" + if payload.action != "write": + return + + old_state = payload.old_values.get("state") + new_state = payload.values.get("state") + + # Order confirmed + if old_state == "draft" and new_state == "sale": + await send_order_confirmation(payload.record_id) + + # Order delivered + elif new_state == "done": + await send_order_delivered(payload.record_id) + + +async def handle_stock_picking_event(payload: OdooWebhookPayload): + """Handle stock picking (delivery) events""" + if payload.action != "write": + return + + new_state = payload.values.get("state") + + # Shipment sent + if new_state == "done": + await send_shipment_notification(payload.record_id) + + +async def handle_invoice_event(payload: OdooWebhookPayload): + """Handle invoice events""" + if payload.action != "write": + return + + # Payment received + if payload.values.get("payment_state") == "paid": + await send_payment_confirmation(payload.record_id) + + +async def send_order_confirmation(order_id: int): + """Send WhatsApp message for order confirmation""" + try: + async with httpx.AsyncClient() as client: + # Get order details + response = await client.get( + f"{settings.API_GATEWAY_URL}/api/odoo/sales/{order_id}", + timeout=10, + ) + if response.status_code != 200: + return + + order = response.json() + + # Get partner details + partner_response = await client.get( + f"{settings.API_GATEWAY_URL}/api/odoo/partners/{order['partner_id']}", + timeout=10, + ) + if partner_response.status_code != 200: + return + + partner = partner_response.json() + phone = partner.get("mobile") or partner.get("phone") + + if not phone: + return + + # Format message + message = f"""*Pedido Confirmado* + +Hola {partner.get('name', '')}, + +Tu pedido *{order['name']}* ha sido confirmado. + +Total: {order['currency']} {order['amount_total']:.2f} + +Gracias por tu compra.""" + + # Send via API Gateway + await client.post( + f"{settings.API_GATEWAY_URL}/api/internal/send-by-phone", + json={"phone": phone, "message": message}, + timeout=10, + ) + except Exception as e: + print(f"Failed to send order confirmation: {e}") + + +async def send_shipment_notification(picking_id: int): + """Send WhatsApp message for shipment""" + # Similar implementation - get picking details and send notification + pass + + +async def send_order_delivered(order_id: int): + """Send WhatsApp message for delivered order""" + # Similar implementation + pass + + +async def send_payment_confirmation(invoice_id: int): + """Send WhatsApp message for payment received""" + # Similar implementation + pass + + +@router.get("/odoo/test") +async def test_webhook(): + """Test endpoint for webhook connectivity""" + return {"status": "ok", "service": "webhooks"}