# app/modules/loyalty/tasks/wallet_sync.py """ Wallet synchronization task. Handles syncing loyalty card data to Google Wallet and Apple Wallet for cards that may have missed real-time updates. """ import logging from celery import shared_task logger = logging.getLogger(__name__) @shared_task(name="loyalty.sync_wallet_passes") def sync_wallet_passes() -> dict: """ Sync wallet passes for cards that may be out of sync. This catches any cards that missed real-time updates due to errors or network issues. Returns: Summary of synced passes """ from datetime import UTC, datetime, timedelta from app.core.database import SessionLocal from app.modules.loyalty.models import LoyaltyCard, LoyaltyTransaction from app.modules.loyalty.services import wallet_service db = SessionLocal() try: # Find cards with transactions in the last hour that have wallet IDs one_hour_ago = datetime.now(UTC) - timedelta(hours=1) # Get card IDs with recent transactions recent_tx_card_ids = ( db.query(LoyaltyTransaction.card_id) .filter(LoyaltyTransaction.transaction_at >= one_hour_ago) .distinct() .all() ) card_ids = [row[0] for row in recent_tx_card_ids] if not card_ids: logger.info("No cards with recent transactions to sync") return { "status": "success", "cards_checked": 0, "google_synced": 0, "apple_synced": 0, } # Get cards with wallet integrations cards = ( db.query(LoyaltyCard) .filter( LoyaltyCard.id.in_(card_ids), (LoyaltyCard.google_object_id.isnot(None)) | (LoyaltyCard.apple_serial_number.isnot(None)), ) .all() ) google_synced = 0 apple_synced = 0 for card in cards: try: results = wallet_service.sync_card_to_wallets(db, card) if results.get("google_wallet"): google_synced += 1 if results.get("apple_wallet"): apple_synced += 1 except Exception as e: logger.warning(f"Failed to sync card {card.id} to wallets: {e}") logger.info( f"Wallet sync complete: {len(cards)} cards checked, " f"{google_synced} Google, {apple_synced} Apple" ) return { "status": "success", "cards_checked": len(cards), "google_synced": google_synced, "apple_synced": apple_synced, } except Exception as e: logger.error(f"Wallet sync task failed: {e}") return { "status": "error", "error": str(e), } finally: db.close()