Skip to content

Commit 9d1fc76

Browse files
committed
editoast: adapt simulation endpoint with new exceptions
Signed-off-by: Egor <egor@berezify.fr>
1 parent 9f4b508 commit 9d1fc76

File tree

5 files changed

+85
-58
lines changed

5 files changed

+85
-58
lines changed

editoast/openapi.yaml

Lines changed: 3 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

editoast/src/views/timetable/paced_train.rs

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use core_client::simulation::PhysicsConsist;
1818
use database::DbConnection;
1919
use database::DbConnectionPoolV2;
2020
use editoast_derive::EditoastError;
21+
use editoast_models::TrainScheduleException;
2122
use editoast_models::prelude::*;
2223
use editoast_models::round_trips::TrainScheduleRoundTrips;
2324
use 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());

front/src/applications/operationalStudies/hooks/useSimulationResults.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -91,7 +91,7 @@ const useSimulationResults = (): {
9191
id: selectedTrainId,
9292
infraId,
9393
electricalProfileSetId,
94-
exceptionKey: exception?.key,
94+
exceptionId: exception?.id ?? undefined,
9595
}
9696
: skipToken
9797
);

front/src/common/api/generatedEditoastApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1354,7 +1354,7 @@ const injectedRtkApi = api
13541354
params: {
13551355
infra_id: queryArg.infraId,
13561356
electrical_profile_set_id: queryArg.electricalProfileSetId,
1357-
exception_key: queryArg.exceptionKey,
1357+
exception_id: queryArg.exceptionId,
13581358
},
13591359
}),
13601360
providesTags: ['paced_train'],
@@ -2632,7 +2632,7 @@ export type GetTrainSchedulesByIdSimulationApiArg = {
26322632
id: number;
26332633
infraId: number;
26342634
electricalProfileSetId?: number;
2635-
exceptionKey?: string;
2635+
exceptionId?: number;
26362636
};
26372637
export type GetVersionApiResponse = /** status 200 Return the service version */ Version;
26382638
export type GetVersionApiArg = void;

front/src/common/api/osrdEditoastApi.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -97,10 +97,10 @@ const osrdEditoastApi = generatedEditoastApi
9797
}),
9898
getTrainSimulation: builder.query<
9999
SimulationResponse,
100-
{ id: TrainId; infraId: number; electricalProfileSetId?: number; exceptionKey?: string }
100+
{ id: TrainId; infraId: number; electricalProfileSetId?: number; exceptionId?: number }
101101
>({
102102
queryFn: async (
103-
{ id: trainId, infraId, electricalProfileSetId, exceptionKey },
103+
{ id: trainId, infraId, electricalProfileSetId, exceptionId },
104104
{ dispatch }
105105
) => {
106106
const pacedTrainId = isOccurrenceId(trainId)
@@ -112,7 +112,7 @@ const osrdEditoastApi = generatedEditoastApi
112112
id: extractEditoastIdFromPacedTrainId(pacedTrainId),
113113
infraId,
114114
electricalProfileSetId,
115-
exceptionKey,
115+
exceptionId,
116116
},
117117
{ subscribe: false }
118118
)

0 commit comments

Comments
 (0)