omni_orchestrator/schemas/v1/api/cost/
projections.rs

1use super::super::super::db::queries as db;
2use super::types::CreateCostProjectionRequest;
3use rocket::http::Status;
4use rocket::serde::json::{json, Json, Value};
5use rocket::{delete, get, post, State};
6use std::sync::Arc;
7use crate::DatabaseManager;
8
9use libomni::types::db::v1 as types;
10use types::cost::CostProjection;
11
12/// List all cost projections with pagination support.
13#[get("/platform/<platform_id>/cost_projections?<page>&<per_page>")]
14pub async fn list_cost_projections(
15    platform_id: i64,
16    page: Option<i64>,
17    per_page: Option<i64>,
18    db_manager: &State<Arc<DatabaseManager>>,
19) -> Result<Json<Value>, (Status, Json<Value>)> {
20    // Get platform information
21    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
22        Ok(platform) => platform,
23        Err(_) => {
24            return Err((
25                Status::NotFound,
26                Json(json!({
27                    "error": "Platform not found",
28                    "message": format!("Platform with ID {} does not exist", platform_id)
29                }))
30            ));
31        }
32    };
33
34    // Get platform-specific database pool
35    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
36        Ok(pool) => pool,
37        Err(_) => {
38            return Err((
39                Status::InternalServerError,
40                Json(json!({
41                    "error": "Database error",
42                    "message": "Failed to connect to platform database"
43                }))
44            ));
45        }
46    };
47
48    match (page, per_page) {
49        (Some(p), Some(pp)) => {
50            let projections = match db::cost::list_cost_projections(&pool, p, pp).await {
51                Ok(projections) => projections,
52                Err(_) => {
53                    return Err((
54                        Status::InternalServerError,
55                        Json(json!({
56                            "error": "Database error",
57                            "message": "Failed to retrieve cost projections"
58                        }))
59                    ));
60                }
61            };
62            
63            let response = json!({
64                "cost_projections": projections,
65                "pagination": {
66                    "page": p,
67                    "per_page": pp
68                }
69            });
70
71            Ok(Json(response))
72        }
73        _ => Err((
74            Status::BadRequest,
75            Json(json!({
76                "error": "Missing pagination parameters",
77                "message": "Please provide both 'page' and 'per_page' parameters"
78            }))
79        ))
80    }
81}
82
83/// Get a specific cost projection by ID.
84#[get("/platform/<platform_id>/cost_projections/<id>")]
85pub async fn get_cost_projection(
86    platform_id: i64,
87    id: i64,
88    db_manager: &State<Arc<DatabaseManager>>,
89) -> Result<Json<CostProjection>, (Status, Json<Value>)> {
90    // Get platform information
91    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
92        Ok(platform) => platform,
93        Err(_) => {
94            return Err((
95                Status::NotFound,
96                Json(json!({
97                    "error": "Platform not found",
98                    "message": format!("Platform with ID {} does not exist", platform_id)
99                }))
100            ));
101        }
102    };
103
104    // Get platform-specific database pool
105    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
106        Ok(pool) => pool,
107        Err(_) => {
108            return Err((
109                Status::InternalServerError,
110                Json(json!({
111                    "error": "Database error",
112                    "message": "Failed to connect to platform database"
113                }))
114            ));
115        }
116    };
117
118    match db::cost::get_cost_projection_by_id(&pool, id).await {
119        Ok(projection) => Ok(Json(projection)),
120        Err(_) => Err((
121            Status::NotFound,
122            Json(json!({
123                "error": "Cost projection not found",
124                "message": format!("Cost projection with ID {} could not be found", id)
125            }))
126        )),
127    }
128}
129
130/// Create a new cost projection.
131#[post("/platform/<platform_id>/cost_projections", format = "json", data = "<request>")]
132pub async fn create_cost_projection(
133    platform_id: i64,
134    request: Json<CreateCostProjectionRequest>,
135    db_manager: &State<Arc<DatabaseManager>>,
136) -> Result<Json<CostProjection>, (Status, Json<Value>)> {
137    // Get platform information
138    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
139        Ok(platform) => platform,
140        Err(_) => {
141            return Err((
142                Status::NotFound,
143                Json(json!({
144                    "error": "Platform not found",
145                    "message": format!("Platform with ID {} does not exist", platform_id)
146                }))
147            ));
148        }
149    };
150
151    // Get platform-specific database pool
152    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
153        Ok(pool) => pool,
154        Err(_) => {
155            return Err((
156                Status::InternalServerError,
157                Json(json!({
158                    "error": "Database error",
159                    "message": "Failed to connect to platform database"
160                }))
161            ));
162        }
163    };
164
165    match db::cost::create_cost_projection(
166        &pool,
167        request.org_id,
168        request.app_id,
169        &request.projection_period,
170        request.start_date,
171        request.end_date,
172        request.projected_cost,
173        &request.currency,
174        &request.projection_model,
175        request.confidence_level,
176        request.metadata.as_deref(),
177    ).await {
178        Ok(projection) => Ok(Json(projection)),
179        Err(e) => Err((
180            Status::InternalServerError,
181            Json(json!({
182                "error": "Failed to create cost projection",
183                "message": format!("{}", e)
184            }))
185        )),
186    }
187}
188
189/// Delete a cost projection.
190#[delete("/platform/<platform_id>/cost_projections/<id>")]
191pub async fn delete_cost_projection(
192    platform_id: i64,
193    id: i64,
194    db_manager: &State<Arc<DatabaseManager>>,
195) -> Result<Json<Value>, (Status, Json<Value>)> {
196    // Get platform information
197    let platform = match db::platforms::get_platform_by_id(db_manager.get_main_pool(), platform_id).await {
198        Ok(platform) => platform,
199        Err(_) => {
200            return Err((
201                Status::NotFound,
202                Json(json!({
203                    "error": "Platform not found",
204                    "message": format!("Platform with ID {} does not exist", platform_id)
205                }))
206            ));
207        }
208    };
209
210    // Get platform-specific database pool
211    let pool = match db_manager.get_platform_pool(&platform.name, platform_id).await {
212        Ok(pool) => pool,
213        Err(_) => {
214            return Err((
215                Status::InternalServerError,
216                Json(json!({
217                    "error": "Database error",
218                    "message": "Failed to connect to platform database"
219                }))
220            ));
221        }
222    };
223
224    match db::cost::delete_cost_projection(&pool, id).await {
225        Ok(_) => Ok(Json(json!({ "status": "deleted" }))),
226        Err(e) => Err((
227            Status::InternalServerError,
228            Json(json!({
229                "error": "Failed to delete cost projection",
230                "message": format!("{}", e)
231            }))
232        )),
233    }
234}