File size: 5,073 Bytes
4ae946d
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import logging
from datetime import datetime, timedelta

from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy import text
from sqlalchemy.orm import Session

from app.modules.auth.service import auth_service
from core.database import User, get_db

from .schemas import TransactionFlowResponse
from .service import AnalyticsTimeframe, analytics_service

logger = logging.getLogger(__name__)

router = APIRouter()


@router.get("/cases")
async def get_case_analytics(
    date_from: str | None = None,
    date_to: str | None = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(auth_service.get_current_user),
):
    """Get optimized case analytics"""
    try:
        date_from_parsed = datetime.fromisoformat(date_from) if date_from else None
        date_to_parsed = datetime.fromisoformat(date_to) if date_to else None

        analytics = analytics_service.get_case_analytics(
            db, date_from_parsed, date_to_parsed
        )
        return analytics
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/transactions")
async def get_transaction_analytics(
    case_id: str | None = None,
    date_from: str | None = None,
    date_to: str | None = None,
    db: Session = Depends(get_db),
    current_user: User = Depends(auth_service.get_current_user),
):
    """Get transaction analytics with optimized aggregates"""
    try:
        date_from_parsed = datetime.fromisoformat(date_from) if date_from else None
        date_to_parsed = datetime.fromisoformat(date_to) if date_to else None

        analytics = analytics_service.get_transaction_aggregates(
            db, case_id, date_from_parsed, date_to_parsed
        )
        return analytics
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/overview")
async def get_system_overview(
    db: Session = Depends(get_db),
    current_user: User = Depends(auth_service.get_current_user),
):
    """Get system overview statistics"""
    try:
        from app.modules.cases.service import case_service

        case_stats = case_service.get_case_stats(db)
        # Get recent cases using CaseService
        recent_cases_data = case_service.get_cases_paginated(
            db, page=1, per_page=5, filters={}
        )
        recent_cases = recent_cases_data.get("cases", [])

        return {
            "case_stats": case_stats,
            "recent_cases": [
                {
                    "id": case.id,
                    "title": case.title,
                    "status": (
                        case.status.value
                        if hasattr(case.status, "value")
                        else case.status
                    ),
                    "created_at": (
                        case.created_at.isoformat() if case.created_at else None
                    ),
                }
                for case in recent_cases
            ],
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/temporal-flow", response_model=list[TransactionFlowResponse])
async def get_temporal_flow(
    days: int = 30,
    limit: int = 2000,
    db: Session = Depends(get_db),
    current_user: User = Depends(auth_service.get_current_user),
):
    """Get temporal flow data for visualization"""
    try:
        cutoff_date = (datetime.now() - timedelta(days=days)).isoformat()
        query = """
        SELECT t.id, t.customer_name, t.merchant_name, t.amount, t.date, t.merchant_category, t.risk_score
        FROM transactions t
        WHERE t.date >= :cutoff_date
        ORDER BY t.date ASC
        LIMIT :limit
        """
        result = db.execute(text(query), {"cutoff_date": cutoff_date, "limit": limit})
        flows = []
        for row in result:
            risk_score = float(row[6]) if row[6] else 0.0
            tx_type = "normal"
            if risk_score > 80:
                tx_type = "flagged"
            elif risk_score > 50:
                tx_type = "suspicious"
            flows.append(
                {
                    "id": str(row[0]),
                    "source": row[1] or "Unknown Source",
                    "target": row[2] or "Unknown Target",
                    "amount": float(row[3]),
                    "timestamp": str(row[4]),
                    "type": tx_type,
                    "category": row[5] or "Uncategorized",
                    "risk_score": risk_score,
                }
            )
        return flows
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/behavioral")
async def get_behavioral_analytics(
    current_user: User = Depends(auth_service.get_current_user),
):
    """Get behavioral analytics for heatmaps"""
    try:
        risk_heatmaps = await analytics_service.generate_risk_heatmaps(
            AnalyticsTimeframe.MONTH
        )
        return risk_heatmaps
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))