Update utils/formatters.py
Browse files- utils/formatters.py +30 -9
utils/formatters.py
CHANGED
|
@@ -507,7 +507,7 @@ def create_card_performance_chart(data: Dict) -> go.Figure:
|
|
| 507 |
if isinstance(rewards_by_card, list):
|
| 508 |
# If it's a list of dicts like [{"card": "Amex", "rewards": 95.50}, ...]
|
| 509 |
for item in rewards_by_card:
|
| 510 |
-
card_name = item.get('card', item.get('card_name', 'Unknown'))
|
| 511 |
reward_value = item.get('rewards', item.get('reward_amount', 0))
|
| 512 |
|
| 513 |
cards.append(card_name)
|
|
@@ -515,24 +515,35 @@ def create_card_performance_chart(data: Dict) -> go.Figure:
|
|
| 515 |
try:
|
| 516 |
rewards.append(float(reward_value))
|
| 517 |
except (ValueError, TypeError):
|
|
|
|
| 518 |
rewards.append(0.0)
|
| 519 |
|
| 520 |
elif isinstance(rewards_by_card, dict):
|
| 521 |
-
# If it's a dict like {"Amex Gold":
|
| 522 |
for card_name, reward_value in rewards_by_card.items():
|
| 523 |
-
cards.append(card_name)
|
| 524 |
-
# Convert to float, handle strings
|
| 525 |
try:
|
| 526 |
-
|
| 527 |
-
|
|
|
|
|
|
|
|
|
|
| 528 |
rewards.append(0.0)
|
| 529 |
|
|
|
|
|
|
|
|
|
|
|
|
|
| 530 |
# If still no data, create sample data
|
| 531 |
if not cards or sum(rewards) == 0:
|
| 532 |
print("⚠️ No card performance data, using sample data")
|
| 533 |
cards = ['Amex Gold', 'Chase Sapphire Reserve', 'Citi Double Cash']
|
| 534 |
rewards = [95.50, 62.00, 30.00]
|
| 535 |
|
|
|
|
|
|
|
|
|
|
| 536 |
# Sort by rewards (highest first)
|
| 537 |
sorted_pairs = sorted(zip(cards, rewards), key=lambda x: x[0], reverse=True)
|
| 538 |
cards = [p[0] for p in sorted_pairs]
|
|
@@ -547,8 +558,17 @@ def create_card_performance_chart(data: Dict) -> go.Figure:
|
|
| 547 |
rewards = rewards[::-1]
|
| 548 |
|
| 549 |
# Create color gradient (darker = better performance)
|
| 550 |
-
max_reward = max(rewards) if rewards else 1
|
| 551 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 552 |
|
| 553 |
fig = go.Figure(data=[go.Bar(
|
| 554 |
y=cards, # Horizontal bar chart
|
|
@@ -558,7 +578,7 @@ def create_card_performance_chart(data: Dict) -> go.Figure:
|
|
| 558 |
color=colors,
|
| 559 |
line=dict(color='#667eea', width=1)
|
| 560 |
),
|
| 561 |
-
text=[f'${r:.2f}' for r in rewards], #
|
| 562 |
textposition='outside',
|
| 563 |
textfont=dict(size=12, color='#333'),
|
| 564 |
hovertemplate='<b>%{y}</b><br>Total Rewards: $%{x:.2f}<extra></extra>'
|
|
@@ -590,6 +610,7 @@ def create_card_performance_chart(data: Dict) -> go.Figure:
|
|
| 590 |
paper_bgcolor='white'
|
| 591 |
)
|
| 592 |
|
|
|
|
| 593 |
return fig
|
| 594 |
|
| 595 |
except Exception as e:
|
|
|
|
| 507 |
if isinstance(rewards_by_card, list):
|
| 508 |
# If it's a list of dicts like [{"card": "Amex", "rewards": 95.50}, ...]
|
| 509 |
for item in rewards_by_card:
|
| 510 |
+
card_name = str(item.get('card', item.get('card_name', 'Unknown')))
|
| 511 |
reward_value = item.get('rewards', item.get('reward_amount', 0))
|
| 512 |
|
| 513 |
cards.append(card_name)
|
|
|
|
| 515 |
try:
|
| 516 |
rewards.append(float(reward_value))
|
| 517 |
except (ValueError, TypeError):
|
| 518 |
+
print(f"⚠️ Could not convert reward value: {reward_value}")
|
| 519 |
rewards.append(0.0)
|
| 520 |
|
| 521 |
elif isinstance(rewards_by_card, dict):
|
| 522 |
+
# If it's a dict like {"Amex Gold": 85.0, "Chase": 62.00}
|
| 523 |
for card_name, reward_value in rewards_by_card.items():
|
| 524 |
+
cards.append(str(card_name))
|
| 525 |
+
# Convert to float, handle strings and any type
|
| 526 |
try:
|
| 527 |
+
reward_float = float(reward_value)
|
| 528 |
+
rewards.append(reward_float)
|
| 529 |
+
print(f"✅ Converted {card_name}: {reward_value} ({type(reward_value)}) -> {reward_float}")
|
| 530 |
+
except (ValueError, TypeError) as e:
|
| 531 |
+
print(f"⚠️ Could not convert reward value for {card_name}: {reward_value} - {e}")
|
| 532 |
rewards.append(0.0)
|
| 533 |
|
| 534 |
+
# Debug: Check what we have
|
| 535 |
+
print(f"📊 Cards: {cards}")
|
| 536 |
+
print(f"📊 Rewards (types): {[(r, type(r)) for r in rewards]}")
|
| 537 |
+
|
| 538 |
# If still no data, create sample data
|
| 539 |
if not cards or sum(rewards) == 0:
|
| 540 |
print("⚠️ No card performance data, using sample data")
|
| 541 |
cards = ['Amex Gold', 'Chase Sapphire Reserve', 'Citi Double Cash']
|
| 542 |
rewards = [95.50, 62.00, 30.00]
|
| 543 |
|
| 544 |
+
# Ensure all rewards are floats (extra safety)
|
| 545 |
+
rewards = [float(r) for r in rewards]
|
| 546 |
+
|
| 547 |
# Sort by rewards (highest first)
|
| 548 |
sorted_pairs = sorted(zip(cards, rewards), key=lambda x: x[0], reverse=True)
|
| 549 |
cards = [p[0] for p in sorted_pairs]
|
|
|
|
| 558 |
rewards = rewards[::-1]
|
| 559 |
|
| 560 |
# Create color gradient (darker = better performance)
|
| 561 |
+
max_reward = float(max(rewards)) if rewards else 1.0 # ← Ensure float
|
| 562 |
+
print(f"📊 Max reward: {max_reward} (type: {type(max_reward)})")
|
| 563 |
+
|
| 564 |
+
# Calculate colors with explicit float division
|
| 565 |
+
colors = []
|
| 566 |
+
for r in rewards:
|
| 567 |
+
r_float = float(r)
|
| 568 |
+
opacity = 0.4 + 0.6 * (r_float / max_reward)
|
| 569 |
+
color = f'rgba(102, 126, 234, {opacity:.2f})'
|
| 570 |
+
colors.append(color)
|
| 571 |
+
print(f" Color for ${r_float:.2f}: {color}")
|
| 572 |
|
| 573 |
fig = go.Figure(data=[go.Bar(
|
| 574 |
y=cards, # Horizontal bar chart
|
|
|
|
| 578 |
color=colors,
|
| 579 |
line=dict(color='#667eea', width=1)
|
| 580 |
),
|
| 581 |
+
text=[f'${float(r):.2f}' for r in rewards], # Explicit float conversion
|
| 582 |
textposition='outside',
|
| 583 |
textfont=dict(size=12, color='#333'),
|
| 584 |
hovertemplate='<b>%{y}</b><br>Total Rewards: $%{x:.2f}<extra></extra>'
|
|
|
|
| 610 |
paper_bgcolor='white'
|
| 611 |
)
|
| 612 |
|
| 613 |
+
print("✅ Chart created successfully!")
|
| 614 |
return fig
|
| 615 |
|
| 616 |
except Exception as e:
|