File size: 7,639 Bytes
b70ff07
 
 
 
 
20adca1
b70ff07
 
 
20adca1
 
 
b70ff07
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
20adca1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
from fastapi import APIRouter, Depends, HTTPException
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select, delete, func
from typing import Dict, Any, List
from datetime import datetime, timedelta
from ..core.dependencies import get_current_active_user, get_db
from ..db.database import get_db
from ..db.models import User, Order, Notification, Event
from ..utils.logger import logger
from ..services.maintenance import maintenance_service
from ..services.pos_analytics import pos_analytics
import asyncio

router = APIRouter()

@router.post("/sessions/cleanup")
async def cleanup_sessions(

    current_user: User = Depends(get_current_active_user),

    db: AsyncSession = Depends(get_db)

) -> Dict[str, int]:
    """Manually trigger session cleanup"""
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=403,
            detail="Only administrators can perform maintenance operations"
        )
    
    cutoff_date = datetime.utcnow() - timedelta(days=7)
    stmt = delete(Event).where(Event.created_at < cutoff_date)
    result = await db.execute(stmt)
    await db.commit()
    
    return {"deleted_sessions": result.rowcount}

@router.post("/data/archive")
async def archive_data(

    current_user: User = Depends(get_current_active_user),

    db: AsyncSession = Depends(get_db)

) -> Dict[str, int]:
    """Manually trigger data archiving"""
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=403,
            detail="Only administrators can perform maintenance operations"
        )
    
    archive_date = datetime.utcnow() - timedelta(days=365)
    archived = {}
    
    # Archive old orders
    orders_stmt = delete(Order).where(
        Order.created_at < archive_date,
        Order.status.in_(["delivered", "cancelled"])
    )
    orders_result = await db.execute(orders_stmt)
    archived["orders"] = orders_result.rowcount
    
    # Archive old notifications
    notif_stmt = delete(Notification).where(
        Notification.created_at < archive_date,
        Notification.read == True
    )
    notif_result = await db.execute(notif_stmt)
    archived["notifications"] = notif_result.rowcount
    
    await db.commit()
    return archived

@router.get("/health")
async def check_health(

    current_user: User = Depends(get_current_active_user),

    db: AsyncSession = Depends(get_db)

) -> Dict[str, Any]:
    """Check system health metrics"""
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=403,
            detail="Only administrators can view system health"
        )
    
    try:
        # Check database connection
        await db.execute(select(1))
        
        # Get database statistics
        total_users = await db.scalar(select(func.count()).select_from(User))
        total_orders = await db.scalar(select(func.count()).select_from(Order))
        total_notifications = await db.scalar(select(func.count()).select_from(Notification))
        
        return {
            "status": "healthy",
            "timestamp": datetime.utcnow(),
            "database": {
                "connected": True,
                "total_users": total_users,
                "total_orders": total_orders,
                "total_notifications": total_notifications
            }
        }
    except Exception as e:
        logger.error(f"Health check error: {str(e)}")
        return {
            "status": "unhealthy",
            "error": str(e),
            "timestamp": datetime.utcnow()
        }

@router.post("/database/maintenance")
async def perform_db_maintenance(

    current_user: User = Depends(get_current_active_user),

    db: AsyncSession = Depends(get_db)

) -> Dict[str, Any]:
    """Manually trigger database maintenance"""
    if "admin" not in current_user.roles:
        raise HTTPException(
            status_code=403,
            detail="Only administrators can perform maintenance operations"
        )
    
    try:
        # Cleanup expired sessions
        await cleanup_sessions(current_user, db)
        
        # Run VACUUM ANALYZE (requires raw SQL)
        await db.execute("VACUUM ANALYZE;")
        
        return {
            "status": "success",
            "message": "Database maintenance completed successfully"
        }
    except Exception as e:
        logger.error(f"Database maintenance error: {str(e)}")
        raise HTTPException(
            status_code=500,
            detail=f"Database maintenance failed: {str(e)}"
        )

@router.get("/health")
async def health_check() -> Dict[str, Any]:
    """Public health check endpoint that doesn't require authentication"""
    return {
        "status": "healthy",
        "timestamp": maintenance_service.get_timestamp()
    }

@router.get("/system-status")
async def get_system_status(

    current_user: User = Depends(get_current_active_user),

    db: AsyncSession = Depends(get_db)

) -> Dict[str, Any]:
    """Get detailed system status including POS integration health"""
    if not current_user.is_superuser:
        raise HTTPException(
            status_code=403,
            detail="Only superusers can access system status"
        )

    # Check database connectivity
    db_status = await maintenance_service.check_database()
    
    # Check POS integration
    pos_status = await pos_analytics.health_check()
    
    # Check Redis connectivity
    redis_status = await maintenance_service.check_redis()
    
    # Check background tasks
    tasks_status = await maintenance_service.check_background_tasks()
    
    return {
        "status": "healthy",
        "timestamp": maintenance_service.get_timestamp(),
        "components": {
            "database": db_status,
            "redis": redis_status,
            "background_tasks": tasks_status,
            "pos_integration": pos_status
        }
    }

@router.post("/sync/pos-metrics")
async def trigger_pos_sync(

    current_user: User = Depends(get_current_active_user)

) -> Dict[str, Any]:
    """Manually trigger POS metrics synchronization"""
    if not current_user.is_superuser:
        raise HTTPException(
            status_code=403,
            detail="Only superusers can trigger manual sync"
        )
    
    try:
        success = await pos_analytics.sync_all_metrics()
        return {
            "status": "success" if success else "partial_failure",
            "message": "POS metrics sync completed successfully" if success else "Some metrics failed to sync"
        }
    except Exception as e:
        raise HTTPException(
            status_code=500,
            detail=f"Failed to sync POS metrics: {str(e)}"
        )

@router.get("/sync/status")
async def get_sync_status(

    current_user: User = Depends(get_current_active_user)

) -> Dict[str, Any]:
    """Get status of background sync tasks"""
    if not current_user.is_superuser:
        raise HTTPException(
            status_code=403,
            detail="Only superusers can view sync status"
        )
    
    tasks_status = await maintenance_service.check_background_tasks()
    pos_health = await pos_analytics.health_check()
    
    return {
        "background_tasks": tasks_status,
        "pos_integration": pos_health,
        "last_sync_timestamp": maintenance_service.get_last_sync_time(),
        "next_sync_due": maintenance_service.get_next_sync_time()
    }