rewardpilot-web-ui / utils /api_client.py
sammy786's picture
Update utils/api_client.py
ccb76e6 verified
raw
history blame
6.91 kB
"""API client for RewardPilot Orchestrator"""
import httpx
from typing import Dict, Optional
from config import ORCHESTRATOR_URL
from typing import Any, Dict, List, Optional, Tuple
import logging
# Create logger
logger = logging.getLogger(__name__)
class RewardPilotClient:
"""Client for interacting with RewardPilot Orchestrator"""
def __init__(self, base_url: str = ORCHESTRATOR_URL):
self.base_url = base_url.rstrip('/')
self.timeout = 30.0
async def get_recommendation(
self,
user_id: str,
merchant: str,
mcc: str,
amount_usd: float,
transaction_date: Optional[str] = None
) -> Dict:
"""Get card recommendation from orchestrator"""
async with httpx.AsyncClient(timeout=self.timeout) as client:
try:
payload = {
"user_id": user_id,
"merchant": merchant,
"mcc": mcc,
"amount_usd": amount_usd
}
if transaction_date:
payload["transaction_date"] = transaction_date
response = await client.post(
f"{self.base_url}/recommend",
json=payload
)
response.raise_for_status()
return response.json()
except httpx.HTTPError as e:
return {
"error": True,
"message": f"API Error: {str(e)}"
}
except Exception as e:
return {
"error": True,
"message": f"Unexpected error: {str(e)}"
}
def get_recommendation_sync(
self,
user_id: str,
merchant: str,
mcc: str,
amount_usd: float,
transaction_date: Optional[str] = None
) -> Dict:
"""Synchronous version for Gradio"""
import asyncio
try:
loop = asyncio.get_event_loop()
except RuntimeError:
loop = asyncio.new_event_loop()
asyncio.set_event_loop(loop)
return loop.run_until_complete(
self.get_recommendation(
user_id, merchant, mcc, amount_usd, transaction_date
)
)
def get_user_analytics(self, user_id: str) -> Dict[str, Any]:
"""
Fetch user analytics including spending patterns and optimization metrics
Args:
user_id: User identifier
Returns:
Dictionary containing analytics data
"""
try:
# Option 1: If you have a dedicated analytics endpoint
response = httpx.get(
f"{self.orchestrator_url}/analytics/{user_id}",
timeout=30.0
)
response.raise_for_status()
return response.json()
except Exception as e:
logger.error(f"Analytics fetch failed: {e}")
# Return mock data as fallback
return self._get_mock_analytics(user_id)
def _get_mock_analytics(self, user_id: str) -> Dict[str, Any]:
"""Generate mock analytics data for demo purposes"""
import random
# Different data per user for variety
user_multipliers = {
"u_alice": 1.2,
"u_bob": 0.9,
"u_charlie": 1.5,
}
multiplier = user_multipliers.get(user_id, 1.0)
return {
"user_id": user_id,
"annual_savings": round(342 * multiplier, 2),
"rate_increase": round(23 * multiplier, 1),
"optimized_transactions": int(156 * multiplier),
"optimization_score": min(100, int(87 * multiplier)),
"category_breakdown": [
{
"category": "πŸ›’ Groceries",
"monthly_spend": round(450 * multiplier, 2),
"best_card": "Amex Gold",
"rewards": round(27 * multiplier, 2),
"rate": "6%"
},
{
"category": "🍽️ Restaurants",
"monthly_spend": round(320 * multiplier, 2),
"best_card": "Amex Gold",
"rewards": round(12.8 * multiplier, 2),
"rate": "4%"
},
{
"category": "β›½ Gas",
"monthly_spend": round(180 * multiplier, 2),
"best_card": "Costco Visa",
"rewards": round(7.2 * multiplier, 2),
"rate": "4%"
},
{
"category": "✈️ Travel",
"monthly_spend": round(850 * multiplier, 2),
"best_card": "Sapphire Reserve",
"rewards": round(42.5 * multiplier, 2),
"rate": "5%"
},
{
"category": "🎬 Entertainment",
"monthly_spend": round(125 * multiplier, 2),
"best_card": "Freedom Unlimited",
"rewards": round(1.88 * multiplier, 2),
"rate": "1.5%"
},
{
"category": "πŸͺ Online Shopping",
"monthly_spend": round(280 * multiplier, 2),
"best_card": "Amazon Prime",
"rewards": round(16.8 * multiplier, 2),
"rate": "6%"
}
],
"total_monthly_spend": round(2205 * multiplier, 2),
"total_monthly_rewards": round(108.18 * multiplier, 2),
"average_rate": round(4.9, 1),
"top_categories": [
{"name": "✈️ Travel", "amount": round(850 * multiplier, 2), "change": "+45%"},
{"name": "πŸ›’ Groceries", "amount": round(450 * multiplier, 2), "change": "+12%"},
{"name": "🍽️ Restaurants", "amount": round(320 * multiplier, 2), "change": "-5%"}
],
"ytd_rewards": round(1298.16 * multiplier, 2),
"ytd_potential": round(1640 * multiplier, 2),
"money_left": round(341.84 * multiplier, 2),
"forecast": {
"next_month_spend": round(2350 * multiplier, 2),
"next_month_rewards": round(115.25 * multiplier, 2),
"cards_to_watch": ["Amex Gold (dining cap)", "Freedom (quarterly bonus)"]
},
"recommendations": [
"πŸ’³ Use Chase Freedom for groceries in Q4 (5% back)",
"⚠️ Monitor Amex Gold dining spend (cap at $2,000)",
"🎯 Book holiday travel with Sapphire Reserve for 5x points"
]
}