fix: Handle null values in dashboard API to prevent React error #306

Fixed critical React error #306 by adding proper null handling for
reasoning and consequence fields in the dashboard service.

Issue: When database columns (reasoning, consequence) contain NULL
values, Python's .get() method returns None, which becomes undefined
in JavaScript, causing React to throw error #306 when trying to render.

Solution: Changed from `.get("field", "default")` to `.get("field") or "default"`
to properly handle None values throughout the dashboard service.

Changes:
- Purchase order actions: Added null coalescing for reasoning/consequence
- Production timeline: Added null coalescing for reasoning field
- Alert actions: Added null coalescing for description and source
- Onboarding actions: Added null coalescing for title and consequence

This ensures all text fields always have valid string values before
being sent to the frontend, preventing undefined rendering errors.
This commit is contained in:
Claude
2025-11-07 18:05:45 +00:00
parent 392bfb186f
commit 6ee8c055ee

View File

@@ -352,8 +352,8 @@ class DashboardService:
"type": ActionType.RESOLVE_ALERT, "type": ActionType.RESOLVE_ALERT,
"urgency": ActionUrgency.CRITICAL, "urgency": ActionUrgency.CRITICAL,
"title": alert["title"], "title": alert["title"],
"subtitle": alert.get("source", "System Alert"), "subtitle": alert.get("source") or "System Alert",
"reasoning": alert.get("description", ""), "reasoning": alert.get("description") or "System alert requires attention",
"consequence": "Immediate action required to prevent production issues", "consequence": "Immediate action required to prevent production issues",
"actions": [ "actions": [
{"label": "View Details", "type": "primary", "action": "view_alert"}, {"label": "View Details", "type": "primary", "action": "view_alert"},
@@ -373,8 +373,8 @@ class DashboardService:
"urgency": urgency, "urgency": urgency,
"title": f"Purchase Order {po.get('po_number', 'N/A')}", "title": f"Purchase Order {po.get('po_number', 'N/A')}",
"subtitle": f"Supplier: {po.get('supplier_name', 'Unknown')}", "subtitle": f"Supplier: {po.get('supplier_name', 'Unknown')}",
"reasoning": po.get("reasoning", "Low stock levels detected"), "reasoning": po.get("reasoning") or "Low stock levels detected",
"consequence": po.get("consequence", "Order needed to maintain inventory levels"), "consequence": po.get("consequence") or "Order needed to maintain inventory levels",
"amount": po.get("total_amount", 0), "amount": po.get("total_amount", 0),
"currency": po.get("currency", "EUR"), "currency": po.get("currency", "EUR"),
"actions": [ "actions": [
@@ -393,14 +393,14 @@ class DashboardService:
"id": f"onboarding_{step['id']}", "id": f"onboarding_{step['id']}",
"type": ActionType.COMPLETE_ONBOARDING, "type": ActionType.COMPLETE_ONBOARDING,
"urgency": ActionUrgency.IMPORTANT, "urgency": ActionUrgency.IMPORTANT,
"title": step["title"], "title": step.get("title") or "Complete onboarding step",
"subtitle": "Setup incomplete", "subtitle": "Setup incomplete",
"reasoning": "Required to unlock full automation", "reasoning": "Required to unlock full automation",
"consequence": step.get("consequence", "Some features are limited"), "consequence": step.get("consequence") or "Some features are limited",
"actions": [ "actions": [
{"label": "Complete Setup", "type": "primary", "action": "complete_onboarding"} {"label": "Complete Setup", "type": "primary", "action": "complete_onboarding"}
], ],
"estimatedTimeMinutes": step.get("estimated_minutes", 10) "estimatedTimeMinutes": step.get("estimated_minutes") or 10
}) })
# Sort by urgency priority # Sort by urgency priority
@@ -505,7 +505,7 @@ class DashboardService:
"progress": progress, "progress": progress,
"readyBy": planned_end.isoformat() if planned_end else None, "readyBy": planned_end.isoformat() if planned_end else None,
"priority": batch.get("priority", "MEDIUM"), "priority": batch.get("priority", "MEDIUM"),
"reasoning": batch.get("reasoning", "Based on demand forecast") "reasoning": batch.get("reasoning") or "Based on demand forecast"
}) })
# Sort by planned start time # Sort by planned start time