"""Response formatting utilities""" from typing import Any, Dict, List, Optional, Tuple import plotly.graph_objects as go import plotly.express as px def format_card_display(card_data: Dict) -> str: """Format card recommendation for display""" card_name = card_data.get("card_name", "Unknown Card") reward_rate = card_data.get("reward_rate", 0) reward_amount = card_data.get("reward_amount", 0) category = card_data.get("category", "General") reasoning = card_data.get("reasoning", "") return f""" ### 💳 {card_name} **Reward Rate:** {reward_rate}x points **Reward Amount:** ${reward_amount:.2f} **Category:** {category} **Why:** {reasoning} """ def format_full_recommendation(response: Dict) -> str: """Format complete recommendation response""" if response.get("error"): return f"❌ **Error:** {response.get('message', 'Unknown error')}" # Header output = f""" # 🎯 Recommendation for {response.get('merchant', 'Unknown')} **Amount:** ${response.get('amount_usd', 0):.2f} **Date:** {response.get('transaction_date', 'N/A')} **User:** {response.get('user_id', 'N/A')} --- ## 🏆 Best Card to Use """ # Recommended card recommended = response.get("recommended_card", {}) output += format_card_display(recommended) # RAG Insights rag_insights = response.get("rag_insights") if rag_insights: output += f""" --- ## 📚 Card Benefits {rag_insights.get('benefits', 'No additional information available.')} """ if rag_insights.get('tips'): output += f""" 💡 **Pro Tip:** {rag_insights.get('tips')} """ # Forecast Warning forecast = response.get("forecast_warning") if forecast: risk_level = forecast.get("risk_level", "low") message = forecast.get("message", "") if risk_level == "high": emoji = "🚨" elif risk_level == "medium": emoji = "⚠️" else: emoji = "✅" output += f""" --- ## {emoji} Spending Status {message} **Current Spend:** ${forecast.get('current_spend', 0):.2f} **Spending Cap:** ${forecast.get('cap', 0):.2f} **Projected Spend:** ${forecast.get('projected_spend', 0):.2f} """ # Alternative cards alternatives = response.get("alternative_cards", []) if alternatives: output += "\n---\n\n## 🔄 Alternative Cards\n\n" for i, alt in enumerate(alternatives[:2], 1): output += f"### Option {i}\n" output += format_card_display(alt) # Metadata services = response.get("services_used", []) time_ms = response.get("orchestration_time_ms", 0) output += f""" --- **Services Used:** {', '.join(services)} **Response Time:** {time_ms:.0f}ms """ return output def format_comparison_table(cards: list) -> str: """Format card comparison as markdown table""" if not cards: return "No cards to compare." table = """ | Card | Reward Rate | Reward Amount | Category | |------|-------------|---------------|----------| """ for card in cards: name = card.get("card_name", "Unknown") rate = card.get("reward_rate", 0) amount = card.get("reward_amount", 0) category = card.get("category", "N/A") table += f"| {name} | {rate}x | ${amount:.2f} | {category} |\n" return table # utils/formatters.py def format_analytics_metrics(analytics: Dict[str, Any]) -> tuple: """ Format analytics data for display Returns: Tuple of (metrics_html, table_md, insights_md, forecast_md) """ # Format metric cards metrics_html = f"""

${analytics['annual_savings']}

💰 Potential Annual Savings

{analytics['rate_increase']}%

📈 Rewards Rate Increase

{analytics['optimized_transactions']}

✅ Optimized Transactions

{analytics['optimization_score']}/100

⭐ Optimization Score

""" # Format spending breakdown table table_rows = [] for cat in analytics['category_breakdown']: table_rows.append( f"| {cat['category']} | ${cat['monthly_spend']:.2f} | {cat['best_card']} | " f"${cat['rewards']:.2f} | {cat['rate']} |" ) table_md = f""" | Category | Monthly Spend | Best Card | Rewards | Rate | |----------|---------------|-----------|---------|------| {chr(10).join(table_rows)} | **Total** | **${analytics['total_monthly_spend']:.2f}** | - | **${analytics['total_monthly_rewards']:.2f}** | **{analytics['average_rate']}%** | """ # Format insights top_cats = "\n".join([ f"{i+1}. {cat['name']}: ${cat['amount']:.2f} ({cat['change']})" for i, cat in enumerate(analytics['top_categories']) ]) insights_md = f""" **🔥 Top Spending Categories:** {top_cats} **💡 Optimization Opportunities:** - ✅ You're using optimal cards {analytics['optimization_score']}% of the time - 🎯 Switch to Chase Freedom for Q4 5% grocery bonus - ⚠️ Amex Gold dining cap approaching ($2,000 limit) - 💳 Consider applying for Citi Custom Cash **🏆 Best Performing Card:** {analytics['category_breakdown'][0]['best_card']} - ${analytics['category_breakdown'][0]['rewards']:.2f} rewards earned **📊 Year-to-Date:** - Total Rewards: ${analytics['ytd_rewards']:.2f} - Potential if optimized: ${analytics['ytd_potential']:.2f} - **Money left on table: ${analytics['money_left']:.2f}** """ # Format forecast forecast = analytics['forecast'] recommendations = "\n".join([f"{i+1}. {rec}" for i, rec in enumerate(analytics['recommendations'])]) forecast_md = f""" ### 🔮 Next Month Forecast Based on your spending patterns: - **Predicted Spend:** ${forecast['next_month_spend']:.2f} - **Predicted Rewards:** ${forecast['next_month_rewards']:.2f} - **Cards to Watch:** {', '.join(forecast['cards_to_watch'])} **Recommendations:** {recommendations} """ return metrics_html, table_md, insights_md, forecast_md def create_spending_chart(analytics: Dict[str, Any]) -> go.Figure: """ Create a bar chart showing spending by category Args: analytics: Analytics data dictionary Returns: Plotly figure object """ categories = [cat['category'] for cat in analytics['category_breakdown']] spending = [cat['monthly_spend'] for cat in analytics['category_breakdown']] rewards = [cat['rewards'] for cat in analytics['category_breakdown']] fig = go.Figure() # Add spending bars fig.add_trace(go.Bar( name='Monthly Spend', x=categories, y=spending, marker_color='rgb(102, 126, 234)', text=[f'${s:.0f}' for s in spending], textposition='outside', )) # Add rewards bars fig.add_trace(go.Bar( name='Rewards Earned', x=categories, y=rewards, marker_color='rgb(56, 239, 125)', text=[f'${r:.2f}' for r in rewards], textposition='outside', )) fig.update_layout( title='💰 Spending vs Rewards by Category', xaxis_title='Category', yaxis_title='Amount ($)', barmode='group', height=400, template='plotly_white', showlegend=True, legend=dict( orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1 ) ) return fig def create_rewards_pie_chart(analytics: Dict[str, Any]) -> go.Figure: """ Create a pie chart showing rewards distribution by category Args: analytics: Analytics data dictionary Returns: Plotly figure object """ categories = [cat['category'] for cat in analytics['category_breakdown']] rewards = [cat['rewards'] for cat in analytics['category_breakdown']] fig = go.Figure(data=[go.Pie( labels=categories, values=rewards, hole=0.4, # Donut chart marker=dict( colors=['#667eea', '#764ba2', '#f093fb', '#f5576c', '#4facfe', '#00f2fe'] ), textinfo='label+percent', textposition='outside', hovertemplate='%{label}
Rewards: $%{value:.2f}
%{percent}' )]) fig.update_layout( title='🎯 Rewards Distribution by Category', height=400, template='plotly_white', showlegend=True, legend=dict( orientation="v", yanchor="middle", y=0.5, xanchor="left", x=1.05 ) ) return fig def create_optimization_gauge(analytics: Dict[str, Any]) -> go.Figure: """ Create a gauge chart showing optimization score Args: analytics: Analytics data dictionary Returns: Plotly figure object """ score = analytics['optimization_score'] fig = go.Figure(go.Indicator( mode="gauge+number+delta", value=score, domain={'x': [0, 1], 'y': [0, 1]}, title={'text': "⭐ Optimization Score", 'font': {'size': 24}}, delta={'reference': 80, 'increasing': {'color': "green"}}, gauge={ 'axis': {'range': [None, 100], 'tickwidth': 1, 'tickcolor': "darkblue"}, 'bar': {'color': "darkblue"}, 'bgcolor': "white", 'borderwidth': 2, 'bordercolor': "gray", 'steps': [ {'range': [0, 50], 'color': '#ffcccb'}, {'range': [50, 75], 'color': '#ffffcc'}, {'range': [75, 100], 'color': '#ccffcc'} ], 'threshold': { 'line': {'color': "red", 'width': 4}, 'thickness': 0.75, 'value': 90 } } )) fig.update_layout( height=300, template='plotly_white', margin=dict(l=20, r=20, t=60, b=20) ) return fig def create_trend_line_chart(analytics: Dict[str, Any]) -> go.Figure: """ Create a line chart showing spending trends (mock data for demo) Args: analytics: Analytics data dictionary Returns: Plotly figure object """ import random # Generate mock monthly data months = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'] # Base spending with some variance base_spend = analytics['total_monthly_spend'] spending_data = [base_spend * (0.8 + random.random() * 0.4) for _ in months] # Calculate rewards based on average rate avg_rate = analytics['average_rate'] / 100 rewards_data = [spend * avg_rate for spend in spending_data] fig = go.Figure() # Add spending line fig.add_trace(go.Scatter( x=months, y=spending_data, mode='lines+markers', name='Monthly Spending', line=dict(color='rgb(102, 126, 234)', width=3), marker=dict(size=8), hovertemplate='%{x}
Spending: $%{y:.2f}' )) # Add rewards line fig.add_trace(go.Scatter( x=months, y=rewards_data, mode='lines+markers', name='Rewards Earned', line=dict(color='rgb(56, 239, 125)', width=3), marker=dict(size=8), hovertemplate='%{x}
Rewards: $%{y:.2f}' )) fig.update_layout( title='📈 12-Month Spending & Rewards Trend', xaxis_title='Month', yaxis_title='Amount ($)', height=400, template='plotly_white', hovermode='x unified', showlegend=True, legend=dict( orientation="h", yanchor="bottom", y=1.02, xanchor="right", x=1 ) ) return fig def create_card_performance_chart(analytics: Dict[str, Any]) -> go.Figure: """ Create a horizontal bar chart showing card performance Args: analytics: Analytics data dictionary Returns: Plotly figure object """ # Aggregate rewards by card card_rewards = {} for cat in analytics['category_breakdown']: card = cat['best_card'] reward = cat['rewards'] if card in card_rewards: card_rewards[card] += reward else: card_rewards[card] = reward # Sort by rewards sorted_cards = sorted(card_rewards.items(), key=lambda x: x[0], reverse=True) cards = [card for card, _ in sorted_cards] rewards = [reward for _, reward in sorted_cards] fig = go.Figure(go.Bar( x=rewards, y=cards, orientation='h', marker=dict( color=rewards, colorscale='Viridis', showscale=True, colorbar=dict(title="Rewards ($)") ), text=[f'${r:.2f}' for r in rewards], textposition='outside', hovertemplate='%{y}
Total Rewards: $%{x:.2f}' )) fig.update_layout( title='🏆 Card Performance Ranking', xaxis_title='Total Rewards Earned ($)', yaxis_title='Credit Card', height=400, template='plotly_white', margin=dict(l=150) ) return fig