@@ -12,7 +12,6 @@ use axum::Extension;
12
12
use derivative:: Derivative ;
13
13
use editoast_authz:: BuiltinRole ;
14
14
use editoast_derive:: EditoastError ;
15
- use editoast_schemas:: train_schedule:: TrainScheduleBase ;
16
15
use itertools:: Itertools ;
17
16
use serde:: Deserialize ;
18
17
use serde:: Serialize ;
@@ -30,25 +29,30 @@ use crate::models::prelude::*;
30
29
use crate :: models:: timetable:: Timetable ;
31
30
use crate :: models:: timetable:: TimetableWithTrains ;
32
31
use crate :: models:: train_schedule:: TrainSchedule ;
33
- use crate :: models:: train_schedule:: TrainScheduleChangeset ;
34
32
use crate :: models:: Infra ;
35
33
use crate :: views:: train_schedule:: train_simulation_batch;
36
- use crate :: views:: train_schedule:: TrainScheduleForm ;
37
34
use crate :: views:: train_schedule:: TrainScheduleResult ;
38
35
use crate :: views:: AuthenticationExt ;
39
36
use crate :: views:: AuthorizationError ;
40
37
use crate :: AppState ;
41
38
use crate :: RetrieveBatch ;
42
39
use editoast_models:: DbConnectionPoolV2 ;
40
+ use editoast_schemas:: train_schedule:: TrainScheduleBase ;
41
+ use crate :: models:: train_schedule:: TrainScheduleChangeset ;
42
+ use crate :: views:: train_schedule:: TrainScheduleForm ;
43
+
44
+ use super :: pagination:: PaginatedList as _;
45
+ use super :: pagination:: PaginationQueryParams ;
46
+ use super :: pagination:: PaginationStats ;
43
47
44
48
crate :: routes! {
45
49
"/timetable" => {
46
50
post,
47
51
"/{id}" => {
48
52
delete,
49
- get,
53
+ "/train_schedules" => get,
54
+ "/train_schedules" => train_schedule,
50
55
"/conflicts" => conflicts,
51
- "/train_schedule" => train_schedule,
52
56
& stdcm,
53
57
} ,
54
58
} ,
@@ -112,37 +116,57 @@ struct TimetableIdParam {
112
116
id : i64 ,
113
117
}
114
118
119
+ #[ derive( Serialize , ToSchema , Debug ) ]
120
+ #[ cfg_attr( test, derive( Deserialize ) ) ]
121
+ struct ListTrainSchedulesResponse {
122
+ #[ schema( value_type = Vec <TrainScheduleResult >) ]
123
+ results : Vec < TrainScheduleResult > ,
124
+ #[ serde( flatten) ]
125
+ stats : PaginationStats ,
126
+ }
127
+
115
128
/// Return a specific timetable with its associated schedules
116
129
#[ utoipa:: path(
117
130
get, path = "" ,
118
131
tag = "timetable" ,
119
132
params( TimetableIdParam ) ,
120
133
responses(
121
- ( status = 200 , description = "Timetable with train schedules ids" , body = TimetableDetailedResult ) ,
134
+ ( status = 200 , description = "Timetable with train schedules ids" , body = inline ( ListTrainSchedulesResponse ) ) ,
122
135
( status = 404 , description = "Timetable not found" ) ,
123
136
) ,
124
137
) ]
125
138
async fn get (
126
139
State ( db_pool) : State < DbConnectionPoolV2 > ,
127
140
Extension ( auth) : AuthenticationExt ,
128
141
Path ( TimetableIdParam { id : timetable_id } ) : Path < TimetableIdParam > ,
129
- ) -> Result < Json < TimetableDetailedResult > > {
142
+ Query ( pagination_params) : Query < PaginationQueryParams > ,
143
+ ) -> Result < Json < ListTrainSchedulesResponse > > {
130
144
let authorized = auth
131
- . check_roles ( [ BuiltinRole :: TimetableRead ] . into ( ) )
132
- . await
133
- . map_err ( AuthorizationError :: AuthError ) ?;
145
+ . check_roles ( [ BuiltinRole :: TimetableRead ] . into ( ) )
146
+ . await
147
+ . map_err ( AuthorizationError :: AuthError ) ?;
134
148
if !authorized {
135
149
return Err ( AuthorizationError :: Forbidden . into ( ) ) ;
136
150
}
137
151
138
152
let conn = & mut db_pool. get ( ) . await ?;
139
- let timetable = TimetableWithTrains :: retrieve_or_fail ( conn, timetable_id, || {
153
+ Timetable :: retrieve_or_fail ( conn, timetable_id, || {
140
154
TimetableError :: NotFound { timetable_id }
141
155
} )
142
156
. await ?;
143
- Ok ( Json ( timetable. into ( ) ) )
157
+
158
+ let settings = pagination_params
159
+ . validate ( 25 ) ?
160
+ . into_selection_settings ( )
161
+ . filter ( move || TrainSchedule :: TIMETABLE_ID . eq ( timetable_id) ) ;
162
+
163
+ let ( train_schedules, stats) = TrainSchedule :: list_paginated ( conn, settings) . await ?;
164
+ let results = train_schedules. into_iter ( ) . map_into ( ) . collect ( ) ;
165
+
166
+ Ok ( Json ( ListTrainSchedulesResponse { stats, results} ) )
144
167
}
145
168
169
+
146
170
/// Create a timetable
147
171
#[ utoipa:: path(
148
172
post, path = "" ,
@@ -362,24 +386,20 @@ mod tests {
362
386
363
387
let timetable = create_timetable ( & mut pool. get_ok ( ) ) . await ;
364
388
365
- let request = app. get ( & format ! ( "/timetable/{}" , timetable. id) ) ;
389
+ let request = app. get ( & format ! ( "/timetable/{}/train_schedules " , timetable. id) ) ;
366
390
367
- let timetable_from_response: TimetableDetailedResult =
391
+ let timetable_from_response: ListTrainSchedulesResponse =
368
392
app. fetch ( request) . assert_status ( StatusCode :: OK ) . json_into ( ) ;
369
-
370
393
assert_eq ! (
371
- timetable_from_response,
372
- TimetableDetailedResult {
373
- timetable_id: timetable. id,
374
- train_ids: vec![ ] ,
375
- }
394
+ timetable_from_response. results. len( ) ,
395
+ 0
376
396
) ;
377
397
}
378
398
379
399
#[ rstest]
380
400
async fn get_unexisting_timetable ( ) {
381
401
let app = TestAppBuilder :: default_app ( ) ;
382
- let request = app. get ( & format ! ( "/timetable/{}" , 0 ) ) ;
402
+ let request = app. get ( & format ! ( "/timetable/{}/train_schedules " , 0 ) ) ;
383
403
app. fetch ( request) . assert_status ( StatusCode :: NOT_FOUND ) ;
384
404
}
385
405
0 commit comments