koprogo_api/infrastructure/web/handlers/
age_request_handlers.rs1use crate::application::dto::age_request_dto::{
2 AddCosignatoryDto, CreateAgeRequestDto, SyndicResponseDto,
3};
4use crate::infrastructure::web::classification_erreurs;
5use crate::infrastructure::web::{AppState, AuthenticatedUser};
6use actix_web::{delete, get, post, put, web, HttpResponse, Responder};
7use uuid::Uuid;
8
9#[post("/buildings/{building_id}/age-requests")]
11pub async fn create_age_request(
12 state: web::Data<AppState>,
13 user: AuthenticatedUser,
14 path: web::Path<Uuid>,
15 body: web::Json<CreateAgeRequestDtoWithoutBuildingId>,
16) -> impl Responder {
17 let organization_id = match user.require_organization() {
18 Ok(id) => id,
19 Err(e) => {
20 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
21 }
22 };
23
24 let building_id = path.into_inner();
25 let dto = CreateAgeRequestDto {
26 building_id,
27 title: body.title.clone(),
28 description: body.description.clone(),
29 };
30
31 match state
32 .age_request_use_cases
33 .create(organization_id, user.user_id, dto)
34 .await
35 {
36 Ok(req) => HttpResponse::Created().json(req),
37 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
38 }
39}
40
41#[get("/buildings/{building_id}/age-requests")]
43pub async fn list_age_requests(
44 state: web::Data<AppState>,
45 user: AuthenticatedUser,
46 path: web::Path<Uuid>,
47) -> impl Responder {
48 let organization_id = match user.require_organization() {
49 Ok(id) => id,
50 Err(e) => {
51 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
52 }
53 };
54
55 match state
56 .age_request_use_cases
57 .list_by_building(path.into_inner(), organization_id)
58 .await
59 {
60 Ok(reqs) => HttpResponse::Ok().json(reqs),
61 Err(e) => HttpResponse::InternalServerError().json(serde_json::json!({"error": e})),
62 }
63}
64
65#[get("/age-requests/{id}")]
67pub async fn get_age_request(
68 state: web::Data<AppState>,
69 user: AuthenticatedUser,
70 path: web::Path<Uuid>,
71) -> impl Responder {
72 let organization_id = match user.require_organization() {
73 Ok(id) => id,
74 Err(e) => {
75 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
76 }
77 };
78
79 match state
80 .age_request_use_cases
81 .get(path.into_inner(), organization_id)
82 .await
83 {
84 Ok(req) => HttpResponse::Ok().json(req),
85 Err(e) => {
86 if classification_erreurs::est_introuvable(&e) {
87 HttpResponse::NotFound().json(serde_json::json!({"error": e}))
88 } else if classification_erreurs::est_interdit(&e) {
89 HttpResponse::Forbidden().json(serde_json::json!({"error": e}))
90 } else {
91 HttpResponse::InternalServerError().json(serde_json::json!({"error": e}))
92 }
93 }
94 }
95}
96
97#[put("/age-requests/{id}/open")]
99pub async fn open_age_request(
100 state: web::Data<AppState>,
101 user: AuthenticatedUser,
102 path: web::Path<Uuid>,
103) -> impl Responder {
104 let organization_id = match user.require_organization() {
105 Ok(id) => id,
106 Err(e) => {
107 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
108 }
109 };
110
111 match state
112 .age_request_use_cases
113 .open(path.into_inner(), organization_id, user.user_id)
114 .await
115 {
116 Ok(req) => HttpResponse::Ok().json(req),
117 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
118 }
119}
120
121#[post("/age-requests/{id}/cosignatories")]
123pub async fn add_cosignatory(
124 state: web::Data<AppState>,
125 user: AuthenticatedUser,
126 path: web::Path<Uuid>,
127 body: web::Json<AddCosignatoryDto>,
128) -> impl Responder {
129 let organization_id = match user.require_organization() {
130 Ok(id) => id,
131 Err(e) => {
132 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
133 }
134 };
135
136 match state
137 .age_request_use_cases
138 .add_cosignatory(path.into_inner(), organization_id, body.into_inner())
139 .await
140 {
141 Ok(req) => HttpResponse::Ok().json(req),
142 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
143 }
144}
145
146#[delete("/age-requests/{id}/cosignatories/{owner_id}")]
148pub async fn remove_cosignatory(
149 state: web::Data<AppState>,
150 user: AuthenticatedUser,
151 path: web::Path<(Uuid, Uuid)>,
152) -> impl Responder {
153 let organization_id = match user.require_organization() {
154 Ok(id) => id,
155 Err(e) => {
156 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
157 }
158 };
159
160 let (id, owner_id) = path.into_inner();
161 match state
162 .age_request_use_cases
163 .remove_cosignatory(id, owner_id, organization_id)
164 .await
165 {
166 Ok(req) => HttpResponse::Ok().json(req),
167 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
168 }
169}
170
171#[post("/age-requests/{id}/submit")]
173pub async fn submit_age_request(
174 state: web::Data<AppState>,
175 user: AuthenticatedUser,
176 path: web::Path<Uuid>,
177) -> impl Responder {
178 let organization_id = match user.require_organization() {
179 Ok(id) => id,
180 Err(e) => {
181 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
182 }
183 };
184
185 match state
186 .age_request_use_cases
187 .submit_to_syndic(path.into_inner(), organization_id, user.user_id)
188 .await
189 {
190 Ok(req) => HttpResponse::Ok().json(req),
191 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
192 }
193}
194
195#[put("/age-requests/{id}/syndic-response")]
197pub async fn syndic_response(
198 state: web::Data<AppState>,
199 user: AuthenticatedUser,
200 path: web::Path<Uuid>,
201 body: web::Json<SyndicResponseDto>,
202) -> impl Responder {
203 let organization_id = match user.require_organization() {
204 Ok(id) => id,
205 Err(e) => {
206 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
207 }
208 };
209
210 match state
211 .age_request_use_cases
212 .syndic_response(path.into_inner(), organization_id, body.into_inner())
213 .await
214 {
215 Ok(req) => HttpResponse::Ok().json(req),
216 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
217 }
218}
219
220#[post("/age-requests/{id}/auto-convocation")]
223pub async fn trigger_auto_convocation(
224 state: web::Data<AppState>,
225 user: AuthenticatedUser,
226 path: web::Path<Uuid>,
227) -> impl Responder {
228 let organization_id = match user.require_organization() {
229 Ok(id) => id,
230 Err(e) => {
231 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
232 }
233 };
234
235 match state
236 .age_request_use_cases
237 .trigger_auto_convocation(path.into_inner(), organization_id)
238 .await
239 {
240 Ok(req) => HttpResponse::Ok().json(req),
241 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
242 }
243}
244
245#[post("/age-requests/{id}/withdraw")]
247pub async fn withdraw_age_request(
248 state: web::Data<AppState>,
249 user: AuthenticatedUser,
250 path: web::Path<Uuid>,
251) -> impl Responder {
252 let organization_id = match user.require_organization() {
253 Ok(id) => id,
254 Err(e) => {
255 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
256 }
257 };
258
259 match state
260 .age_request_use_cases
261 .withdraw(path.into_inner(), organization_id, user.user_id)
262 .await
263 {
264 Ok(req) => HttpResponse::Ok().json(req),
265 Err(e) => HttpResponse::BadRequest().json(serde_json::json!({"error": e})),
266 }
267}
268
269#[delete("/age-requests/{id}")]
271pub async fn delete_age_request(
272 state: web::Data<AppState>,
273 user: AuthenticatedUser,
274 path: web::Path<Uuid>,
275) -> impl Responder {
276 let organization_id = match user.require_organization() {
277 Ok(id) => id,
278 Err(e) => {
279 return HttpResponse::Unauthorized().json(serde_json::json!({"error": e.to_string()}))
280 }
281 };
282
283 match state
284 .age_request_use_cases
285 .delete(path.into_inner(), organization_id, user.user_id)
286 .await
287 {
288 Ok(()) => HttpResponse::NoContent().finish(),
289 Err(e) => {
290 if classification_erreurs::est_introuvable(&e) {
291 HttpResponse::NotFound().json(serde_json::json!({"error": e}))
292 } else if classification_erreurs::est_interdit(&e) {
293 HttpResponse::Forbidden().json(serde_json::json!({"error": e}))
294 } else {
295 HttpResponse::BadRequest().json(serde_json::json!({"error": e}))
296 }
297 }
298 }
299}
300
301#[derive(serde::Deserialize)]
303pub struct CreateAgeRequestDtoWithoutBuildingId {
304 pub title: String,
305 pub description: Option<String>,
306}