Spaces:
Build error
Build error
| from collections import defaultdict | |
| from sqlalchemy.orm import Session | |
| from app.database.models import Subscription | |
| def analyze_subscriptions(db: Session, user_id: str): | |
| """ | |
| Analyzes subscriptions to detect duplicates, unused memberships, and cancellation opportunities. | |
| """ | |
| subs = db.query(Subscription).filter( | |
| Subscription.user_id == user_id, | |
| Subscription.active == True | |
| ).all() | |
| if not subs: | |
| return { | |
| "subscriptions": [], | |
| "duplicates": [], | |
| "unused_subscriptions": [], | |
| "yearly_savings_potential": 0.0, | |
| "risk_analysis": [] | |
| } | |
| merchant_map = defaultdict(list) | |
| unused_list = [] | |
| cancellation_suggestions = [] | |
| yearly_savings = 0.0 | |
| risk_analysis = [] | |
| for s in subs: | |
| # Standardize merchant name to detect duplicates | |
| clean_merchant = s.merchant.strip().lower() | |
| merchant_map[clean_merchant].append(s) | |
| # Determine cost | |
| m_cost = s.amount if s.billing_cycle.lower() == "monthly" else (s.amount / 12) | |
| y_cost = (s.amount * 12) if s.billing_cycle.lower() == "monthly" else s.amount | |
| # Detect unused (if frequency is 'low' or 'none' in usage detection metadata) | |
| usage = s.ai_usage_detection or {} | |
| freq = str(usage.get("usage_frequency", "medium")).lower() | |
| if freq in ["low", "none", "unused"]: | |
| unused_list.append(s) | |
| cancellation_suggestions.append({ | |
| "subscription_id": s.id, | |
| "merchant": s.merchant, | |
| "amount": s.amount, | |
| "billing_cycle": s.billing_cycle, | |
| "reason": f"Usage frequency is flagged as '{freq}'.", | |
| "yearly_savings": round(y_cost, 2) | |
| }) | |
| yearly_savings += y_cost | |
| # Detect duplicates | |
| duplicates = [] | |
| for merchant, items in merchant_map.items(): | |
| if len(items) > 1: | |
| total_cost = sum(x.amount for x in items) | |
| duplicates.append({ | |
| "merchant": items[0].merchant, | |
| "count": len(items), | |
| "items": [ | |
| { | |
| "id": x.id, | |
| "amount": x.amount, | |
| "billing_cycle": x.billing_cycle | |
| } | |
| for x in items | |
| ], | |
| "recommendation": f"You have {len(items)} active subscriptions for {items[0].merchant}. Consolidate to a single account to save." | |
| }) | |
| # Risk Analysis (utilities vs entertainment) | |
| essential_categories = ["electricity", "water", "gas", "internet", "phone", "insurance"] | |
| for s in subs: | |
| is_essential = any(k in s.merchant.lower() for k in essential_categories) | |
| if is_essential: | |
| risk_analysis.append({ | |
| "merchant": s.merchant, | |
| "risk_level": "high", | |
| "consequences": "Utility interruption, account reactivation fees, or legal service contract breaches." | |
| }) | |
| else: | |
| risk_analysis.append({ | |
| "merchant": s.merchant, | |
| "risk_level": "low", | |
| "consequences": "Loss of entertainment streaming access only. Service can be reactivated instantly." | |
| }) | |
| return { | |
| "subscriptions": [ | |
| { | |
| "id": s.id, | |
| "merchant": s.merchant, | |
| "amount": s.amount, | |
| "billing_cycle": s.billing_cycle, | |
| "usage_frequency": s.ai_usage_detection.get("usage_frequency", "medium") if s.ai_usage_detection else "medium" | |
| } | |
| for s in subs | |
| ], | |
| "duplicates": duplicates, | |
| "unused_subscriptions": cancellation_suggestions, | |
| "yearly_savings_potential": round(yearly_savings, 2), | |
| "risk_analysis": risk_analysis | |
| } | |