File size: 4,550 Bytes
c40c447
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
"""
Forecast API endpoints.

Responsabilidad: Manejar requests de forecasting y delegar a use cases.
"""

from fastapi import APIRouter, Depends, HTTPException, status
from typing import List

from app.api.dependencies import (
    get_forecast_univariate_use_case,
    get_forecast_multi_series_use_case
)
from app.application.use_cases.forecast_use_case import (
    ForecastUnivariateUseCase,
    ForecastMultiSeriesUseCase
)
from app.application.dtos.forecast_dtos import (
    ForecastUnivariateRequestDTO,
    ForecastUnivariateResponseDTO,
    ForecastMultiSeriesRequestDTO,
    ForecastMultiSeriesResponseDTO
)
from app.utils.logger import setup_logger

logger = setup_logger(__name__)

router = APIRouter(prefix="/forecast", tags=["Forecast"])


@router.post(
    "/univariate",
    response_model=ForecastUnivariateResponseDTO,
    status_code=status.HTTP_200_OK,
    summary="Pron贸stico univariado",
    description="Genera pron贸stico para una serie temporal sin covariables"
)
async def forecast_univariate(
    request: ForecastUnivariateRequestDTO,
    use_case: ForecastUnivariateUseCase = Depends(get_forecast_univariate_use_case)
):
    """
    Pron贸stico univariado.
    
    Genera pron贸stico probabil铆stico para una serie temporal simple,
    sin variables ex贸genas.
    
    Args:
        request: Datos de la serie y par谩metros de predicci贸n
        use_case: Caso de uso inyectado
        
    Returns:
        Pron贸stico con mediana y cuantiles
        
    Raises:
        HTTPException: Si hay error en la predicci贸n
        
    Example:
        ```json
        {
            "values": [100, 102, 105, 103, 108, 112],
            "prediction_length": 3,
            "freq": "D",
            "quantile_levels": [0.1, 0.5, 0.9]
        }
        ```
    """
    try:
        logger.info(
            f"Forecast univariate request: {len(request.values)} values, "
            f"{request.prediction_length} steps ahead"
        )
        
        # Ejecutar use case
        response = use_case.execute(request)
        
        logger.info(f"Forecast completed: {len(response.timestamps)} predictions")
        return response
        
    except ValueError as e:
        logger.error(f"Validation error: {e}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(f"Unexpected error in forecast: {e}", exc_info=True)
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error interno al generar pron贸stico"
        )


@router.post(
    "/multi-series",
    response_model=ForecastMultiSeriesResponseDTO,
    status_code=status.HTTP_200_OK,
    summary="Pron贸stico multi-series",
    description="Genera pron贸sticos para m煤ltiples series simult谩neamente"
)
async def forecast_multi_series(
    request: ForecastMultiSeriesRequestDTO,
    use_case: ForecastMultiSeriesUseCase = Depends(get_forecast_multi_series_use_case)
):
    """
    Pron贸stico para m煤ltiples series.
    
    Genera pron贸sticos independientes para varias series temporales
    en una sola llamada.
    
    Args:
        request: Lista de series y par谩metros
        use_case: Caso de uso inyectado
        
    Returns:
        Lista de pron贸sticos, uno por cada serie
        
    Example:
        ```json
        {
            "series_list": [
                {"series_id": "sales", "values": [100, 102, 105]},
                {"series_id": "revenue", "values": [200, 205, 210]}
            ],
            "prediction_length": 3,
            "freq": "D"
        }
        ```
    """
    try:
        logger.info(
            f"Forecast multi-series request: {len(request.series_list)} series"
        )
        
        # Ejecutar use case
        response = use_case.execute(request)
        
        logger.info(
            f"Multi-series forecast completed: "
            f"{len(response.forecasts)} forecasts"
        )
        return response
        
    except ValueError as e:
        logger.error(f"Validation error: {e}")
        raise HTTPException(
            status_code=status.HTTP_400_BAD_REQUEST,
            detail=str(e)
        )
    except Exception as e:
        logger.error(
            f"Unexpected error in multi-series forecast: {e}",
            exc_info=True
        )
        raise HTTPException(
            status_code=status.HTTP_500_INTERNAL_SERVER_ERROR,
            detail="Error interno al generar pron贸sticos"
        )