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` | |
| ```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 | |