@@ -1119,6 +1119,7 @@ pub(in crate::views) async fn occupancy_blocks(
11191119 Extension ( auth) : AuthenticationExt ,
11201120 Json ( OccupancyBlockForm {
11211121 infra_id,
1122+ timetable_id,
11221123 ids : train_schedule_ids,
11231124 path,
11241125 electrical_profile_set_id,
@@ -1154,21 +1155,39 @@ pub(in crate::views) async fn occupancy_blocks(
11541155 } )
11551156 . await ?;
11561157
1158+ let mut exceptions =
1159+ editoast_models:: TrainScheduleException :: retrieve_exceptions_by_train_schedules (
1160+ conn,
1161+ timetable_id,
1162+ train_schedules. iter ( ) . map ( |t| t. id ) . collect :: < Vec < _ > > ( ) ,
1163+ )
1164+ . await ?
1165+ . into_iter ( )
1166+ . map_into :: < schemas:: TrainScheduleException > ( )
1167+ . into_group_map_by ( |e| e. train_schedule_id ) ;
1168+
11571169 let simulation_contexts: Vec < SimulationContext > = train_schedules
11581170 . iter ( )
11591171 . flat_map ( |train_schedule| {
1172+ let ts_exceptions = exceptions. remove ( & train_schedule. id ) . unwrap_or_default ( ) ;
11601173 std:: iter:: once ( SimulationContext {
11611174 paced_train_id : train_schedule. id ,
11621175 exception_key : None ,
11631176 train_schedule : train_schedule. clone ( ) . into_train_occurrence ( ) ,
11641177 } )
1165- . chain ( train_schedule. exceptions . iter ( ) . map ( |exception| {
1166- SimulationContext {
1167- paced_train_id : train_schedule. id ,
1168- exception_key : Some ( exception. key . clone ( ) ) ,
1169- train_schedule : train_schedule. apply_exception ( exception) ,
1170- }
1171- } ) )
1178+ . chain (
1179+ ts_exceptions
1180+ . iter ( )
1181+ . map ( |exception| {
1182+ SimulationContext {
1183+ paced_train_id : train_schedule. id ,
1184+ exception_key : exception. key . clone ( ) , // TODO use exception.id
1185+ train_schedule : train_schedule
1186+ . apply_train_schedule_exception ( exception) ,
1187+ }
1188+ } )
1189+ . collect :: < Vec < _ > > ( ) ,
1190+ )
11721191 } )
11731192 . collect ( ) ;
11741193
@@ -1679,6 +1698,7 @@ mod tests {
16791698 use editoast_models:: TrainScheduleException ;
16801699 use editoast_models:: prelude:: * ;
16811700 use editoast_models:: rolling_stock:: TrainMainCategory ;
1701+ use editoast_models:: timetable:: Timetable ;
16821702 use pretty_assertions:: assert_eq;
16831703 use rstest:: rstest;
16841704 use schemas:: TrainScheduleExceptionChangeGroups ;
@@ -1687,7 +1707,6 @@ mod tests {
16871707 use schemas:: infra:: Direction ;
16881708 use schemas:: paced_train:: InitialSpeedChangeGroup ;
16891709 use schemas:: paced_train:: Paced ;
1690- use schemas:: paced_train:: PacedTrainException ;
16911710 use schemas:: paced_train:: RollingStockChangeGroup ;
16921711 use schemas:: paced_train:: TrainNameChangeGroup ;
16931712 use schemas:: paced_train:: TrainSchedule ;
@@ -2041,8 +2060,13 @@ mod tests {
20412060 assert_eq ! ( response. train_schedule, paced_train. into( ) ) ;
20422061 }
20432062
2044- async fn app_infra_id_paced_train_id_for_simulation_tests ( )
2045- -> ( TestApp , i64 , i64 , TrainScheduleException ) {
2063+ async fn app_infra_id_paced_train_id_for_simulation_tests ( ) -> (
2064+ TestApp ,
2065+ i64 ,
2066+ Timetable ,
2067+ models:: TrainSchedule ,
2068+ TrainScheduleException ,
2069+ ) {
20462070 let db_pool = DbConnectionPoolV2 :: for_tests ( ) ;
20472071 let small_infra = create_small_infra ( & mut db_pool. get_ok ( ) ) . await ;
20482072 let rolling_stock =
@@ -2051,7 +2075,7 @@ mod tests {
20512075 create_timetable_with_train_schedule_set ( & mut db_pool. get_ok ( ) ) . await ;
20522076 let exception = create_created_exception_with_change_groups ( "created_exception_key" ) ;
20532077
2054- let paced_train_base = TrainSchedule {
2078+ let train_schedule_base = TrainSchedule {
20552079 train_occurrence : TrainOccurrence {
20562080 rolling_stock_name : rolling_stock. name . clone ( ) ,
20572081 ..TrainOccurrence :: fake ( )
@@ -2062,8 +2086,8 @@ mod tests {
20622086 exceptions : vec ! [ ] ,
20632087 } ) ,
20642088 } ;
2065- let paced_train : TrainScheduleChangeset = paced_train_base . into ( ) ;
2066- let paced_train = paced_train
2089+ let train_schedule : TrainScheduleChangeset = train_schedule_base . into ( ) ;
2090+ let train_schedule = train_schedule
20672091 . train_schedule_set_id ( train_schedule_set. id )
20682092 . create ( & mut db_pool. get_ok ( ) )
20692093 . await
@@ -2072,7 +2096,7 @@ mod tests {
20722096 let exception = create_train_schedule_exception (
20732097 & mut db_pool. get_ok ( ) ,
20742098 timetable. id ,
2075- paced_train . id ,
2099+ train_schedule . id ,
20762100 None ,
20772101 Some ( "created_exception_key" . to_string ( ) ) ,
20782102 Some ( exception. change_groups ) ,
@@ -2084,16 +2108,19 @@ mod tests {
20842108 . db_pool ( db_pool)
20852109 . core_client ( core. into ( ) )
20862110 . build ( ) ;
2087- ( app, small_infra. id , paced_train . id , exception)
2111+ ( app, small_infra. id , timetable , train_schedule , exception)
20882112 }
20892113
20902114 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
20912115 async fn paced_train_simulation ( ) {
2092- let ( app, infra_id, train_schedule_id , _exception) =
2116+ let ( app, infra_id, _timetable , train_schedule , _exception) =
20932117 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
20942118 let request = app. get (
2095- format ! ( "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}" )
2096- . as_str ( ) ,
2119+ format ! (
2120+ "/train_schedules/{}/simulation/?infra_id={infra_id}" ,
2121+ train_schedule. id
2122+ )
2123+ . as_str ( ) ,
20972124 ) ;
20982125 let response: core_client:: simulation:: Response = app
20992126 . fetch ( request)
@@ -2106,11 +2133,12 @@ mod tests {
21062133
21072134 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
21082135 async fn paced_train_exception_simulation_with_invalid_exception_key ( ) {
2109- let ( app, infra_id, train_schedule_id , _exception) =
2136+ let ( app, infra_id, _timetable , train_schedule , _exception) =
21102137 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
21112138 let request = app. get (
21122139 format ! (
2113- "/train_schedules/{train_schedule_id}/simulation/?infra_id={infra_id}&exception_id=9999"
2140+ "/train_schedules/{}/simulation/?infra_id={infra_id}&exception_id=9999" ,
2141+ train_schedule. id
21142142 )
21152143 . as_str ( ) ,
21162144 ) ;
@@ -2128,12 +2156,12 @@ mod tests {
21282156
21292157 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
21302158 async fn paced_train_exception_simulation ( ) {
2131- let ( app, infra_id, train_schedule_id , exception) =
2159+ let ( app, infra_id, _timetable , train_schedule , exception) =
21322160 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
21332161 let request = app. get (
21342162 format ! (
2135- "/train_schedules/{train_schedule_id }/simulation/?infra_id={infra_id}&exception_id={}" ,
2136- exception. id
2163+ "/train_schedules/{}/simulation/?infra_id={infra_id}&exception_id={}" ,
2164+ train_schedule . id , exception. id
21372165 )
21382166 . as_str ( ) ,
21392167 ) ;
@@ -2188,7 +2216,7 @@ mod tests {
21882216 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
21892217 async fn paced_train_exception_simulation_with_rolling_stock_not_found ( ) {
21902218 // GIVEN
2191- let ( app, infra_id, train_schedule_id , exception) =
2219+ let ( app, infra_id, _timetable , train_schedule , exception) =
21922220 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
21932221
21942222 let mut change_groupe = exception. change_groups ;
@@ -2198,16 +2226,16 @@ mod tests {
21982226 } ) ;
21992227 let exception = editoast_models:: TrainScheduleException :: changeset ( )
22002228 . change_groups ( change_groupe)
2201- . update ( & mut app. db_pool ( ) . get_ok ( ) , train_schedule_id )
2229+ . update ( & mut app. db_pool ( ) . get_ok ( ) , train_schedule . id )
22022230 . await
22032231 . expect ( "Fail to update exception" )
22042232 . expect ( "Fail to update exception" ) ;
22052233
22062234 // WHEN
22072235 let request = app. get (
22082236 format ! (
2209- "/train_schedules/{train_schedule_id }/simulation/?infra_id={infra_id}&exception_id={}" ,
2210- exception. id
2237+ "/train_schedules/{}/simulation/?infra_id={infra_id}&exception_id={}" ,
2238+ train_schedule . id , exception. id
22112239 )
22122240 . as_str ( ) ,
22132241 ) ;
@@ -2232,7 +2260,7 @@ mod tests {
22322260
22332261 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
22342262 async fn paced_train_simulation_not_found ( ) {
2235- let ( app, infra_id, _paced_train_id , _exception) =
2263+ let ( app, infra_id, _timetable , _train_schedule , _exception) =
22362264 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
22372265 let request =
22382266 app. get ( format ! ( "/train_schedules/{}/simulation/?infra_id={}" , 0 , infra_id) . as_str ( ) ) ;
@@ -2358,7 +2386,7 @@ mod tests {
23582386
23592387 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
23602388 async fn paced_train_simulation_summary_not_found ( ) {
2361- let ( app, infra_id, _paced_train_id, _exception) =
2389+ let ( app, infra_id, _timetable , _paced_train_id, _exception) =
23622390 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
23632391 let timetable = create_timetable ( & mut app. db_pool ( ) . get_ok ( ) ) . await ;
23642392 let request = app
@@ -2696,67 +2724,50 @@ mod tests {
26962724
26972725 #[ tokio:: test( flavor = "multi_thread" , worker_threads = 1 ) ]
26982726 async fn paced_train_occupancy_blocks ( ) {
2699- let ( app, infra_id, paced_train_id , _exception ) =
2727+ let ( app, infra_id, timetable , train_schedule , exception ) =
27002728 app_infra_id_paced_train_id_for_simulation_tests ( ) . await ;
2729+ let db_pool = app. db_pool ( ) ;
27012730
2702- let request = app. get ( format ! ( "/train_schedules/{paced_train_id}" ) . as_str ( ) ) ;
2703- let mut paced_train_response: TrainScheduleResponse = app
2704- . fetch ( request)
2705- . await
2706- . assert_status ( StatusCode :: OK )
2707- . json_into ( ) ;
27082731 // First remove all already generated exceptions
2709- paced_train_response
2710- . train_schedule
2711- . paced
2712- . as_mut ( )
2713- . unwrap ( )
2714- . exceptions
2715- . clear ( ) ;
2732+ exception
2733+ . delete ( & mut db_pool. get_ok ( ) )
2734+ . await
2735+ . expect ( "Failled to remove exception" ) ;
27162736
27172737 // Add one exception which will not change the simulation from base
2718- paced_train_response
2719- . train_schedule
2720- . paced
2721- . as_mut ( )
2722- . unwrap ( )
2723- . exceptions
2724- . push ( PacedTrainException {
2725- key : "change_train_name" . to_string ( ) ,
2726- change_groups : TrainScheduleExceptionChangeGroups {
2727- train_name : Some ( TrainNameChangeGroup {
2728- value : "exception_name_but_same_simulation" . into ( ) ,
2729- } ) ,
2730- ..Default :: default ( )
2731- } ,
2738+ let _exception1 = create_train_schedule_exception (
2739+ & mut db_pool. get_ok ( ) ,
2740+ timetable. id ,
2741+ train_schedule. id ,
2742+ None ,
2743+ Some ( "change_train_name" . to_string ( ) ) ,
2744+ Some ( TrainScheduleExceptionChangeGroups {
2745+ train_name : Some ( TrainNameChangeGroup {
2746+ value : "exception_name_but_same_simulation" . into ( ) ,
2747+ } ) ,
27322748 ..Default :: default ( )
2733- } ) ;
2749+ } ) ,
2750+ )
2751+ . await ;
2752+
27342753 // Add one exception which will change the simulation from base
2735- // and therefore add another entry in the response (field `exceptions`)
2736- paced_train_response
2737- . train_schedule
2738- . paced
2739- . as_mut ( )
2740- . unwrap ( )
2741- . exceptions
2742- . push ( PacedTrainException {
2743- key : "change_initial_speed" . to_string ( ) ,
2744- change_groups : TrainScheduleExceptionChangeGroups {
2745- initial_speed : Some ( InitialSpeedChangeGroup { value : 1.23 } ) ,
2746- ..Default :: default ( )
2747- } ,
2754+ let _exception1 = create_train_schedule_exception (
2755+ & mut db_pool. get_ok ( ) ,
2756+ timetable. id ,
2757+ train_schedule. id ,
2758+ None ,
2759+ Some ( "change_initial_speed" . to_string ( ) ) ,
2760+ Some ( TrainScheduleExceptionChangeGroups {
2761+ initial_speed : Some ( InitialSpeedChangeGroup { value : 1.23 } ) ,
27482762 ..Default :: default ( )
2749- } ) ;
2750- let request = app
2751- . put ( format ! ( "/train_schedules/{paced_train_id}" ) . as_str ( ) )
2752- . json ( & json ! ( paced_train_response. train_schedule) ) ;
2753- app. fetch ( request)
2754- . await
2755- . assert_status ( StatusCode :: NO_CONTENT ) ;
2763+ } ) ,
2764+ )
2765+ . await ;
27562766
27572767 let request = app. post ( "/train_schedules/occupancy_blocks" ) . json (
2758- & json ! ( { "ids" : vec![ paced_train_id ] ,
2768+ & json ! ( { "ids" : vec![ train_schedule . id ] ,
27592769 "infra_id" : infra_id,
2770+ "timetable_id" : timetable. id,
27602771 "path" : {
27612772 "track_section_ranges" : [ {
27622773 "track_section" : "T1" ,
@@ -2775,10 +2786,17 @@ mod tests {
27752786 assert_eq ! ( response. len( ) , 1 ) ;
27762787 // TODO fix mocked simulation to return path item times that respect times
27772788 assert_eq ! (
2778- response. get( & paced_train_id) . unwrap( ) . train_schedule. len( ) ,
2789+ response
2790+ . get( & train_schedule. id)
2791+ . unwrap( )
2792+ . train_schedule
2793+ . len( ) ,
2794+ 0
2795+ ) ;
2796+ assert_eq ! (
2797+ response. get( & train_schedule. id) . unwrap( ) . exceptions. len( ) ,
27792798 0
27802799 ) ;
2781- assert_eq ! ( response. get( & paced_train_id) . unwrap( ) . exceptions. len( ) , 0 ) ;
27822800 }
27832801
27842802 fn pathfinding_result_success ( ) -> PathfindingResultSuccess {
0 commit comments