@@ -18,6 +18,7 @@ use core_client::simulation::PhysicsConsist;
1818use database:: DbConnection ;
1919use database:: DbConnectionPoolV2 ;
2020use editoast_derive:: EditoastError ;
21+ use editoast_models:: TrainScheduleException ;
2122use editoast_models:: prelude:: * ;
2223use editoast_models:: round_trips:: TrainScheduleRoundTrips ;
2324use itertools:: Itertools ;
@@ -400,6 +401,12 @@ pub(in crate::views) struct ExceptionQueryParam {
400401 exception_key : Option < String > ,
401402}
402403
404+ #[ derive( Debug , Default , Clone , Serialize , Deserialize , IntoParams , ToSchema ) ]
405+ #[ into_params( parameter_in = Query ) ]
406+ pub ( in crate :: views) struct TrainScheduleExceptionQueryParam {
407+ exception_id : Option < i64 > ,
408+ }
409+
403410/// Get a path from a paced train given an infrastructure id and a paced train id
404411#[ editoast_derive:: route]
405412#[ utoipa:: path(
@@ -494,7 +501,7 @@ pub struct ElectricalProfileSetIdQueryParam {
494501#[ utoipa:: path(
495502 get, path = "" ,
496503 tag = "paced_train" ,
497- params( TrainScheduleIdParam , InfraIdQueryParam , ElectricalProfileSetIdQueryParam , ExceptionQueryParam ) ,
504+ params( TrainScheduleIdParam , InfraIdQueryParam , ElectricalProfileSetIdQueryParam , TrainScheduleExceptionQueryParam ) ,
498505 responses(
499506 ( status = 200 , description = "Simulation Output" , body = simulation:: Response ) ,
500507 ) ,
@@ -515,7 +522,9 @@ pub(in crate::views) async fn simulation(
515522 Query ( ElectricalProfileSetIdQueryParam {
516523 electrical_profile_set_id,
517524 } ) : Query < ElectricalProfileSetIdQueryParam > ,
518- Query ( ExceptionQueryParam { exception_key } ) : Query < ExceptionQueryParam > ,
525+ Query ( TrainScheduleExceptionQueryParam { exception_id } ) : Query <
526+ TrainScheduleExceptionQueryParam ,
527+ > ,
519528) -> Result < Json < simulation:: Response > > {
520529 let authorized = auth
521530 . check_roles ( [ authz:: Role :: OperationalStudies ] . into ( ) )
@@ -546,17 +555,20 @@ pub(in crate::views) async fn simulation(
546555 } )
547556 . await ?;
548557
549- let train_schedule = match exception_key {
550- Some ( exception_key) => {
551- let exception = train_schedule
552- . exceptions
553- . iter ( )
554- . find ( |e| e. key == exception_key)
555- . ok_or_else ( || TrainScheduleError :: ExceptionNotFound {
556- exception_key : exception_key. clone ( ) ,
557- } ) ?;
558-
559- train_schedule. apply_exception ( exception)
558+ let train_schedule = match exception_id {
559+ Some ( exception_id) => {
560+ let exception = TrainScheduleException :: retrieve_or_fail (
561+ db_pool. get ( ) . await ?,
562+ exception_id,
563+ || {
564+ TrainScheduleError :: ExceptionNotFound {
565+ // TODO rename to exception_id
566+ exception_key : exception_id. to_string ( ) ,
567+ }
568+ } ,
569+ )
570+ . await ?;
571+ train_schedule. apply_train_schedule_exception ( & exception. into ( ) )
560572 }
561573 None => train_schedule. into_train_occurrence ( ) ,
562574 } ;
@@ -1601,6 +1613,7 @@ mod tests {
16011613 use core_client:: simulation:: ReportTrain ;
16021614 use core_client:: simulation:: SpeedLimitProperties ;
16031615 use database:: DbConnectionPoolV2 ;
1616+ use editoast_models:: TrainScheduleException ;
16041617 use editoast_models:: prelude:: * ;
16051618 use editoast_models:: rolling_stock:: TrainMainCategory ;
16061619 use pretty_assertions:: assert_eq;
@@ -1636,6 +1649,8 @@ mod tests {
16361649 use crate :: models:: fixtures:: create_paced_train_with_exceptions;
16371650 use crate :: models:: fixtures:: create_simple_paced_train;
16381651 use crate :: models:: fixtures:: create_small_infra;
1652+ use crate :: models:: fixtures:: create_timetable_with_train_schedule_set;
1653+ use crate :: models:: fixtures:: create_train_schedule_exception;
16391654 use crate :: models:: fixtures:: create_train_schedule_set;
16401655 use crate :: models:: fixtures:: simple_paced_train_base;
16411656 use crate :: models:: fixtures:: simple_paced_train_changeset;
@@ -1963,12 +1978,16 @@ mod tests {
19631978 assert_eq ! ( response. train_schedule, paced_train. into( ) ) ;
19641979 }
19651980
1966- async fn app_infra_id_paced_train_id_for_simulation_tests ( ) -> ( TestApp , i64 , i64 ) {
1981+ async fn app_infra_id_paced_train_id_for_simulation_tests ( )
1982+ -> ( TestApp , i64 , i64 , TrainScheduleException ) {
19671983 let db_pool = DbConnectionPoolV2 :: for_tests ( ) ;
19681984 let small_infra = create_small_infra ( & mut db_pool. get_ok ( ) ) . await ;
1969- let train_schedule_set = create_train_schedule_set ( & mut db_pool. get_ok ( ) ) . await ;
19701985 let rolling_stock =
19711986 create_fast_rolling_stock ( & mut db_pool. get_ok ( ) , "simulation_rolling_stock" ) . await ;
1987+ let ( timetable, train_schedule_set) =
1988+ create_timetable_with_train_schedule_set ( & mut db_pool. get_ok ( ) ) . await ;
1989+ let exception = create_created_exception_with_change_groups ( "created_exception_key" ) ;
1990+
19721991 let paced_train_base = TrainSchedule {
19731992 train_occurrence : TrainOccurrence {
19741993 rolling_stock_name : rolling_stock. name . clone ( ) ,
@@ -1977,9 +1996,7 @@ mod tests {
19771996 paced : Some ( Paced {
19781997 time_window : Duration :: hours ( 1 ) . try_into ( ) . unwrap ( ) ,
19791998 interval : Duration :: minutes ( 15 ) . try_into ( ) . unwrap ( ) ,
1980- exceptions : vec ! [ create_created_exception_with_change_groups(
1981- "created_exception_key" ,
1982- ) ] ,
1999+ exceptions : vec ! [ ] ,
19832000 } ) ,
19842001 } ;
19852002 let paced_train: TrainScheduleChangeset = paced_train_base. into ( ) ;
@@ -1988,17 +2005,28 @@ mod tests {
19882005 . create ( & mut db_pool. get_ok ( ) )
19892006 . await
19902007 . expect ( "Failed to create paced train" ) ;
2008+
2009+ let exception = create_train_schedule_exception (
2010+ & mut db_pool. get_ok ( ) ,
2011+ timetable. id ,
2012+ paced_train. id ,
2013+ None ,
2014+ Some ( "created_exception_key" . to_string ( ) ) ,
2015+ Some ( exception. change_groups ) ,
2016+ )
2017+ . await ;
2018+
19912019 let core = mocked_core_pathfinding_sim_and_proj ( ) ;
19922020 let app = TestAppBuilder :: new ( )
19932021 . db_pool ( db_pool)
19942022 . core_client ( core. into ( ) )
19952023 . build ( ) ;
1996- ( app, small_infra. id , paced_train. id )
2024+ ( app, small_infra. id , paced_train. id , exception )
19972025 }
19982026
19992027 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
20002028 async fn paced_train_simulation ( ) {
2001- let ( app, infra_id, train_schedule_id) =
2029+ let ( app, infra_id, train_schedule_id, _exception ) =
20022030 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
20032031 let request = app. get (
20042032 format ! ( "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}" )
@@ -2015,11 +2043,11 @@ mod tests {
20152043
20162044 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
20172045 async fn paced_train_exception_simulation_with_invalid_exception_key ( ) {
2018- let ( app, infra_id, train_schedule_id) =
2046+ let ( app, infra_id, train_schedule_id, _exception ) =
20192047 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
20202048 let request = app. get (
20212049 format ! (
2022- "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_key=toto "
2050+ "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_id=9999 "
20232051 )
20242052 . as_str ( ) ,
20252053 ) ;
@@ -2037,10 +2065,14 @@ mod tests {
20372065
20382066 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
20392067 async fn paced_train_exception_simulation ( ) {
2040- let ( app, infra_id, train_schedule_id) =
2068+ let ( app, infra_id, train_schedule_id, exception ) =
20412069 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
20422070 let request = app. get (
2043- format ! ( "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_key=created_exception_key" ) . as_str ( ) ,
2071+ format ! (
2072+ "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_id={}" ,
2073+ exception. id
2074+ )
2075+ . as_str ( ) ,
20442076 ) ;
20452077 let response: simulation:: Response = app
20462078 . fetch ( request)
@@ -2093,34 +2125,28 @@ mod tests {
20932125 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
20942126 async fn paced_train_exception_simulation_with_rolling_stock_not_found ( ) {
20952127 // GIVEN
2096- let ( app, infra_id, train_schedule_id) =
2128+ let ( app, infra_id, train_schedule_id, exception ) =
20972129 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
2098- let request = app. get ( format ! ( "/train_schedules/{train_schedule_id}" ) . as_str ( ) ) ;
2099- let mut paced_train_response: TrainScheduleResponse = app
2100- . fetch ( request)
2101- . await
2102- . assert_status ( StatusCode :: OK )
2103- . json_into ( ) ;
2104- paced_train_response
2105- . train_schedule
2106- . paced
2107- . as_mut ( )
2108- . unwrap ( )
2109- . exceptions [ 0 ]
2110- . change_groups
2111- . rolling_stock = Some ( RollingStockChangeGroup {
2130+
2131+ let mut change_groupe = exception. change_groups ;
2132+ change_groupe. rolling_stock = Some ( RollingStockChangeGroup {
21122133 rolling_stock_name : "R2D2" . into ( ) ,
21132134 comfort : Comfort :: AirConditioning ,
21142135 } ) ;
2115- let request = app
2116- . put ( format ! ( "/train_schedules/{train_schedule_id}" ) . as_str ( ) )
2117- . json ( & json ! ( paced_train_response. train_schedule) ) ;
2118- app. fetch ( request)
2136+ let exception = editoast_models:: TrainScheduleException :: changeset ( )
2137+ . change_groups ( change_groupe)
2138+ . update ( & mut app. db_pool ( ) . get_ok ( ) , train_schedule_id)
21192139 . await
2120- . assert_status ( StatusCode :: NO_CONTENT ) ;
2140+ . expect ( "Fail to update exception" )
2141+ . expect ( "Fail to update exception" ) ;
2142+
21212143 // WHEN
21222144 let request = app. get (
2123- format ! ( "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_key=created_exception_key" ) . as_str ( ) ,
2145+ format ! (
2146+ "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_id={}" ,
2147+ exception. id
2148+ )
2149+ . as_str ( ) ,
21242150 ) ;
21252151 let response: simulation:: Response = app
21262152 . fetch ( request)
@@ -2143,7 +2169,7 @@ mod tests {
21432169
21442170 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
21452171 async fn paced_train_simulation_not_found ( ) {
2146- let ( app, infra_id, _paced_train_id) =
2172+ let ( app, infra_id, _paced_train_id, _exception ) =
21472173 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
21482174 let request =
21492175 app. get ( format ! ( "/train_schedules/{}/simulation/?infra_id={}" , 0 , infra_id) . as_str ( ) ) ;
@@ -2159,7 +2185,7 @@ mod tests {
21592185
21602186 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
21612187 async fn paced_train_simulation_summary ( ) {
2162- let ( app, infra_id, paced_train_id) =
2188+ let ( app, infra_id, paced_train_id, _exception ) =
21632189 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
21642190 let request = app. get ( format ! ( "/train_schedules/{paced_train_id}" ) . as_str ( ) ) ;
21652191 let mut paced_train_response: TrainScheduleResponse = app
@@ -2263,7 +2289,7 @@ mod tests {
22632289
22642290 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
22652291 async fn paced_train_simulation_summary_not_found ( ) {
2266- let ( app, infra_id, _paced_train_id) =
2292+ let ( app, infra_id, _paced_train_id, _exception ) =
22672293 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
22682294 let request = app
22692295 . post ( "/train_schedules/simulation_summary" )
@@ -2557,8 +2583,8 @@ mod tests {
25572583 }
25582584
25592585 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
2560- async fn train_schedule_occupancy_blocks ( ) {
2561- let ( app, infra_id, paced_train_id) =
2586+ async fn paced_train_occupancy_blocks ( ) {
2587+ let ( app, infra_id, paced_train_id, _exception ) =
25622588 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
25632589
25642590 let request = app. get ( format ! ( "/train_schedules/{paced_train_id}" ) . as_str ( ) ) ;
0 commit comments