Spaces:
Running
Running
Dashboard Integration Examples
Quick Integration Guide
This document shows exactly how to integrate dashboard updates in your existing code.
1. Order Service Integration
Update app/orders/services/service.py
# Add import at the top
from app.dashboard.utils import update_on_order_created, update_on_order_status_changed
# In create_order method, after order is created:
@staticmethod
async def create_order(partner_id: str, order_data: OrderCreateRequest):
try:
# ... existing order creation code ...
# After successful order creation
order = SpaPartnerOrder(...)
session.add(order)
await session.commit()
# β
ADD THIS: Update dashboard
await update_on_order_created(partner_id)
return {
"success": True,
"message": "Order created successfully",
"order": OrderResponse.model_validate(order_with_items)
}
except Exception as e:
logger.error("Error creating order", exc_info=e)
return {"success": False, "message": str(e)}
Update Order Status
# In update_order_status method:
@staticmethod
async def update_order_status(order_id: UUID, new_status: str):
try:
# ... existing status update code ...
order.order_status = new_status
await session.commit()
# β
ADD THIS: Update dashboard
await update_on_order_status_changed(order.partner_id)
return {"success": True, "order": order}
except Exception as e:
logger.error("Error updating order status", exc_info=e)
return {"success": False}
2. Wallet Service Integration
Update app/wallet/services/service.py
# Add import at the top
from app.dashboard.utils import update_on_wallet_transaction, update_on_payment_received
# In create_transaction method:
@staticmethod
async def create_transaction(
partner_id: str,
amount: Decimal,
transaction_type: str,
reference_type: Optional[str] = None,
reference_id: Optional[str] = None,
description: Optional[str] = None
):
try:
# ... existing transaction creation code ...
transaction = SpaWalletTransaction(...)
session.add(transaction)
await session.commit()
# β
ADD THIS: Update dashboard
await update_on_wallet_transaction(partner_id)
return {"success": True, "transaction": transaction}
except Exception as e:
logger.error("Error creating transaction", exc_info=e)
return {"success": False}
Payment Processing
# In process_payment method:
@staticmethod
async def process_payment(order_id: UUID, payment_data: dict):
try:
# ... existing payment processing code ...
# Update order payment status
order.payment_status = "paid"
await session.commit()
# β
ADD THIS: Update dashboard
await update_on_payment_received(order.partner_id)
return {"success": True, "payment": payment}
except Exception as e:
logger.error("Error processing payment", exc_info=e)
return {"success": False}
3. Leave/Booking Service Integration
Update app/leave/services/service.py
# Add import at the top
from app.dashboard.utils import update_dashboard_on_transaction
# In create_leave method:
@staticmethod
async def create_leave(partner_id: str, leave_data: dict):
try:
# ... existing leave creation code ...
leave = SpaPartnerLeave(...)
session.add(leave)
await session.commit()
# β
ADD THIS: Update dashboard
await update_dashboard_on_transaction(partner_id, "booking_created")
return {"success": True, "leave": leave}
except Exception as e:
logger.error("Error creating leave", exc_info=e)
return {"success": False}
Update Leave Status
# In update_leave_status method:
@staticmethod
async def update_leave_status(leave_id: UUID, new_status: str):
try:
# ... existing status update code ...
leave.status = new_status
await session.commit()
# β
ADD THIS: Update dashboard
await update_dashboard_on_transaction(leave.partner_id, "booking_updated")
return {"success": True, "leave": leave}
except Exception as e:
logger.error("Error updating leave status", exc_info=e)
return {"success": False}
4. Rating Service Integration (Future)
When rating tables are created:
# In app/ratings/services/service.py
from app.dashboard.utils import update_on_rating_submitted
@staticmethod
async def submit_rating(partner_id: str, rating_data: dict):
try:
# ... rating creation code ...
rating = PartnerRating(...)
session.add(rating)
await session.commit()
# β
ADD THIS: Update dashboard
await update_on_rating_submitted(partner_id)
return {"success": True, "rating": rating}
except Exception as e:
logger.error("Error submitting rating", exc_info=e)
return {"success": False}
5. Background Job for Bulk Refresh
Create app/jobs/dashboard_refresh.py
"""
Background job to refresh stale dashboard summaries.
Run this periodically (e.g., every 10 minutes).
"""
import asyncio
from insightfy_utils.logging import get_logger
from app.dashboard.services.mongo_persistence import dashboard_mongo
from app.dashboard.utils import bulk_update_dashboards
logger = get_logger(__name__)
async def refresh_stale_dashboards():
"""Refresh dashboards that haven't been updated in 10 minutes"""
try:
# Get stale partner IDs
stale_ids = await dashboard_mongo.get_stale_summaries(minutes=10)
if not stale_ids:
logger.info("No stale dashboards found")
return
logger.info(f"Found {len(stale_ids)} stale dashboards, refreshing...")
# Bulk update
results = await bulk_update_dashboards(stale_ids, "scheduled_refresh")
logger.info(
"Dashboard refresh completed",
extra={
"total": results["total"],
"success": results["success"],
"failed": results["failed"]
}
)
except Exception as e:
logger.error("Error in dashboard refresh job", exc_info=e)
if __name__ == "__main__":
# For testing
asyncio.run(refresh_stale_dashboards())
Schedule with Cron
# Add to crontab
# Refresh stale dashboards every 10 minutes
*/10 * * * * cd /path/to/app && python -m app.jobs.dashboard_refresh
Or use APScheduler
# In app/main.py
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from app.jobs.dashboard_refresh import refresh_stale_dashboards
scheduler = AsyncIOScheduler()
@app.on_event("startup")
async def startup_event():
# ... existing startup code ...
# Schedule dashboard refresh every 10 minutes
scheduler.add_job(
refresh_stale_dashboards,
'interval',
minutes=10,
id='dashboard_refresh'
)
scheduler.start()
logger.info("Dashboard refresh job scheduled")
@app.on_event("shutdown")
async def shutdown_event():
# ... existing shutdown code ...
scheduler.shutdown()
6. Testing Integration
Test Dashboard Update
# test_dashboard_integration.py
import asyncio
from app.dashboard.utils import update_on_order_created
from app.dashboard.services.mongo_persistence import dashboard_mongo
from app.sql import connect_to_database
from app.nosql import connect_to_mongo
async def test_integration():
# Initialize connections
await connect_to_database()
await connect_to_mongo()
test_partner_id = "PARTNER001"
# Simulate order creation
print(f"Updating dashboard for {test_partner_id}...")
success = await update_on_order_created(test_partner_id)
if success:
print("β
Dashboard updated successfully")
# Verify in MongoDB
doc = await dashboard_mongo.get_summary(test_partner_id)
if doc:
print(f"β
Found in MongoDB: {doc['summary']['bookings']['total_bookings']} bookings")
else:
print("β Not found in MongoDB")
else:
print("β Dashboard update failed")
if __name__ == "__main__":
asyncio.run(test_integration())
7. Error Handling Best Practices
Always Wrap Dashboard Updates
# β
Good - Dashboard update failure doesn't break main operation
async def create_order(partner_id: str, order_data: dict):
try:
# Create order
order = await _create_order_logic(partner_id, order_data)
# Update dashboard (non-blocking)
try:
await update_on_order_created(partner_id)
except Exception as e:
logger.error("Dashboard update failed", exc_info=e)
# Continue - order was created successfully
return {"success": True, "order": order}
except Exception as e:
logger.error("Order creation failed", exc_info=e)
return {"success": False, "message": str(e)}
Use Fire-and-Forget for Non-Critical Updates
# For non-critical updates, use background task
from fastapi import BackgroundTasks
@router.post("/orders")
async def create_order(
order_data: OrderCreateRequest,
background_tasks: BackgroundTasks,
token_data: dict = Depends(verify_token)
):
partner_id = token_data["partner_id"]
# Create order
result = await order_service.create_order(partner_id, order_data)
# Update dashboard in background
background_tasks.add_task(update_on_order_created, partner_id)
return result
8. Monitoring Integration
Add Metrics
# In app/dashboard/utils.py
from prometheus_client import Counter, Histogram
dashboard_updates = Counter(
'dashboard_updates_total',
'Total dashboard updates',
['transaction_type', 'status']
)
dashboard_update_duration = Histogram(
'dashboard_update_duration_seconds',
'Dashboard update duration',
['transaction_type']
)
async def update_dashboard_on_transaction(
partner_id: str,
transaction_type: str = "transaction"
) -> bool:
with dashboard_update_duration.labels(transaction_type).time():
try:
# ... existing code ...
dashboard_updates.labels(
transaction_type=transaction_type,
status='success'
).inc()
return True
except Exception as e:
dashboard_updates.labels(
transaction_type=transaction_type,
status='failed'
).inc()
raise
Summary
Integration Checklist
- Add dashboard update to order creation
- Add dashboard update to order status changes
- Add dashboard update to wallet transactions
- Add dashboard update to payment processing
- Add dashboard update to booking/leave operations
- Set up background job for stale refresh
- Add error handling around updates
- Add monitoring/metrics
- Test integration with sample data
- Deploy and monitor
Key Points
- Always call update functions after transactions
- Use specific functions (update_on_order_created, etc.)
- Handle errors gracefully - don't break main operations
- Use background tasks for non-critical updates
- Monitor update success rate with metrics
- Schedule bulk refresh for stale data
Performance Impact
- Dashboard update: ~50-100ms
- Non-blocking: Use background tasks
- Minimal overhead: Only updates MongoDB
- Redis populated on next API request