# 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` ```python # 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 ```python # 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` ```python # 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 ```python # 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` ```python # 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 ```python # 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: ```python # 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` ```python """ 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 ```bash # Add to crontab # Refresh stale dashboards every 10 minutes */10 * * * * cd /path/to/app && python -m app.jobs.dashboard_refresh ``` ### Or use APScheduler ```python # 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 ```python # 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 ```python # ✅ 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 ```python # 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 ```python # 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 1. **Always call update functions** after transactions 2. **Use specific functions** (update_on_order_created, etc.) 3. **Handle errors gracefully** - don't break main operations 4. **Use background tasks** for non-critical updates 5. **Monitor update success rate** with metrics 6. **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