Skip to content

Commit 2a5ca28

Browse files
Wadjetztheocrsb
authored andcommitted
editoast: adapt train schedule get path endpoint to use exceptions table (#15690)
fix #15593 part of #15202 adapt `GET /train_schedule/{id}/path` endpoint with new exceptions with incremental refactoring to be able to have small PR and adapt endpoints one by one - [x] Use exception id in query string - [x] Adapts tests to use new exceptions > [!NOTE] > This PR targets a feature branch and may contain all its commits, as it has not been rebased yet. Only the last commit need to be reviewed. Signed-off-by: Egor <egor@berezify.fr>
1 parent efa23b1 commit 2a5ca28

File tree

6 files changed

+109
-64
lines changed

6 files changed

+109
-64
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: 67 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -431,7 +431,9 @@ pub(in crate::views) async fn get_path(
431431
id: train_schedule_id,
432432
}): Path<TrainScheduleIdParam>,
433433
Query(InfraIdQueryParam { infra_id }): Query<InfraIdQueryParam>,
434-
Query(ExceptionQueryParam { exception_key }): Query<ExceptionQueryParam>,
434+
Query(TrainScheduleExceptionQueryParam { exception_id }): Query<
435+
TrainScheduleExceptionQueryParam,
436+
>,
435437
) -> Result<Json<PathfindingResult>> {
436438
let authorized = auth
437439
.check_roles([authz::Role::OperationalStudies, authz::Role::Stdcm].into())
@@ -462,17 +464,17 @@ pub(in crate::views) async fn get_path(
462464
})
463465
.await?;
464466

465-
let train_schedule = match exception_key {
466-
Some(exception_key) => {
467-
let exception = paced_train
468-
.exceptions
469-
.iter()
470-
.find(|e| e.key == exception_key)
471-
.ok_or_else(|| TrainScheduleError::ExceptionNotFound {
472-
exception_key: exception_key.clone(),
473-
})?;
474-
475-
paced_train.apply_exception(exception)
467+
let train_schedule = match exception_id {
468+
Some(exception_id) => {
469+
let exception =
470+
TrainScheduleException::retrieve_or_fail(conn.clone(), exception_id, || {
471+
TrainScheduleError::ExceptionNotFound {
472+
// TODO rename to exception_id
473+
exception_key: exception_id.to_string(),
474+
}
475+
})
476+
.await?;
477+
paced_train.apply_train_schedule_exception(&exception.into())
476478
}
477479
None => paced_train.into_train_occurrence(),
478480
};
@@ -1668,6 +1670,8 @@ mod tests {
16681670
use crate::models::fixtures::create_paced_train_with_exceptions;
16691671
use crate::models::fixtures::create_simple_paced_train;
16701672
use crate::models::fixtures::create_small_infra;
1673+
use crate::models::fixtures::create_timetable_with_train_schedule_set;
1674+
use crate::models::fixtures::create_train_schedule_exception;
16711675
use crate::models::fixtures::create_train_schedule_set;
16721676
use crate::models::fixtures::simple_paced_train_base;
16731677
use crate::models::fixtures::simple_paced_train_changeset;
@@ -2370,7 +2374,7 @@ mod tests {
23702374
create_simple_paced_train(&mut pool.get_ok(), train_schedule_set.id).await;
23712375
let request = app.get(
23722376
format!(
2373-
"/train_schedules/{}/path/?infra_id={}&exception_key=toto",
2377+
"/train_schedules/{}/path/?infra_id={}&exception_id=1234",
23742378
paced_train.id, small_infra.id
23752379
)
23762380
.as_str(),
@@ -2455,24 +2459,40 @@ mod tests {
24552459
let db_pool = app.db_pool();
24562460

24572461
create_fast_rolling_stock(&mut db_pool.get_ok(), "R2D2").await;
2458-
let train_schedule_set = create_train_schedule_set(&mut db_pool.get_ok()).await;
2459-
let mut exception = create_created_exception_with_change_groups("exception_created_key");
2460-
exception.change_groups.rolling_stock = Some(RollingStockChangeGroup {
2461-
rolling_stock_name: "exception_rolling_stock".into(),
2462-
comfort: Comfort::Standard,
2463-
});
2464-
let paced_train = create_paced_train_with_exceptions(
2462+
let (timetable, train_schedule_set) =
2463+
create_timetable_with_train_schedule_set(&mut db_pool.get_ok()).await;
2464+
2465+
let train_schedule = create_paced_train_with_exceptions(
24652466
&mut db_pool.get_ok(),
24662467
train_schedule_set.id,
2467-
vec![exception.clone()],
2468+
vec![],
2469+
)
2470+
.await;
2471+
2472+
let change_rolling_stock_exception = create_train_schedule_exception(
2473+
&mut db_pool.get_ok(),
2474+
timetable.id,
2475+
train_schedule.id,
2476+
None,
2477+
Some("exception_for_get_path".to_string()),
2478+
Some(TrainScheduleExceptionChangeGroups {
2479+
train_name: Some(TrainNameChangeGroup {
2480+
value: "exception_name_for_get_path".into(),
2481+
}),
2482+
rolling_stock: Some(RollingStockChangeGroup {
2483+
rolling_stock_name: "exception_rolling_stock".into(),
2484+
comfort: Comfort::Standard,
2485+
}),
2486+
..Default::default()
2487+
}),
24682488
)
24692489
.await;
24702490

24712491
let small_infra = create_small_infra(&mut db_pool.get_ok()).await;
24722492

24732493
let request = app.get(&format!(
2474-
"/train_schedules/{}/path?infra_id={}&exception_key={}",
2475-
paced_train.id, small_infra.id, exception.key
2494+
"/train_schedules/{}/path?infra_id={}&exception_id={}",
2495+
train_schedule.id, small_infra.id, change_rolling_stock_exception.id
24762496
));
24772497

24782498
let response = app
@@ -2510,21 +2530,38 @@ mod tests {
25102530
let app = TestAppBuilder::new().core_client(core.into()).build();
25112531
let db_pool = app.db_pool();
25122532

2513-
create_fast_rolling_stock(&mut db_pool.get_ok(), "simulation_rolling_stock").await;
2514-
let train_schedule_set = create_train_schedule_set(&mut db_pool.get_ok()).await;
2515-
let exception = create_created_exception_with_change_groups("exception_created_key");
2516-
let paced_train = create_paced_train_with_exceptions(
2533+
let (timetable, train_schedule_set) =
2534+
create_timetable_with_train_schedule_set(&mut db_pool.get_ok()).await;
2535+
2536+
create_fast_rolling_stock(&mut db_pool.get_ok(), "R2D2").await;
2537+
2538+
let train_schedule = create_paced_train_with_exceptions(
25172539
&mut db_pool.get_ok(),
25182540
train_schedule_set.id,
2519-
vec![exception.clone()],
2541+
vec![],
2542+
)
2543+
.await;
2544+
2545+
let change_train_name_exception = create_train_schedule_exception(
2546+
&mut db_pool.get_ok(),
2547+
timetable.id,
2548+
train_schedule.id,
2549+
None,
2550+
Some("exception_for_get_path".to_string()),
2551+
Some(TrainScheduleExceptionChangeGroups {
2552+
train_name: Some(TrainNameChangeGroup {
2553+
value: "exception_name_for_get_path".into(),
2554+
}),
2555+
..Default::default()
2556+
}),
25202557
)
25212558
.await;
25222559

25232560
let small_infra = create_small_infra(&mut db_pool.get_ok()).await;
25242561

25252562
let request = app.get(&format!(
2526-
"/train_schedules/{}/path?infra_id={}&exception_key={}",
2527-
paced_train.id, small_infra.id, exception.key
2563+
"/train_schedules/{}/path?infra_id={}&exception_id={}",
2564+
train_schedule.id, small_infra.id, change_train_name_exception.id
25282565
));
25292566

25302567
let response = app

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

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ const useSimulationResults = (): {
8383
? {
8484
id: selectedTrainId,
8585
infraId,
86-
exceptionKey: exception?.key,
86+
exceptionId: exception?.id ?? undefined,
8787
}
8888
: skipToken
8989
);

front/src/common/api/generatedEditoastApi.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1339,7 +1339,7 @@ const injectedRtkApi = api
13391339
url: `/train_schedules/${queryArg.id}/path`,
13401340
params: {
13411341
infra_id: queryArg.infraId,
1342-
exception_key: queryArg.exceptionKey,
1342+
exception_id: queryArg.exceptionId,
13431343
},
13441344
}),
13451345
providesTags: ['train_schedule', 'pathfinding'],
@@ -2623,7 +2623,7 @@ export type GetTrainSchedulesByIdPathApiResponse = /** status 200 The path */ Pa
26232623
export type GetTrainSchedulesByIdPathApiArg = {
26242624
id: number;
26252625
infraId: number;
2626-
exceptionKey?: string;
2626+
exceptionId?: number;
26272627
};
26282628
export type GetTrainSchedulesByIdSimulationApiResponse =
26292629
/** status 200 Simulation Output */ SimulationResponse;

front/src/common/api/osrdEditoastApi.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -74,9 +74,9 @@ const osrdEditoastApi = generatedEditoastApi
7474
}),
7575
getTrainPath: builder.query<
7676
PathfindingResult,
77-
{ id: TrainId; infraId: number; exceptionKey?: string }
77+
{ id: TrainId; infraId: number; exceptionId?: number }
7878
>({
79-
queryFn: async ({ id: trainId, infraId, exceptionKey }, { dispatch }) => {
79+
queryFn: async ({ id: trainId, infraId, exceptionId }, { dispatch }) => {
8080
const pacedTrainId = isOccurrenceId(trainId)
8181
? extractPacedTrainIdFromOccurrenceId(trainId)
8282
: trainId;
@@ -85,7 +85,7 @@ const osrdEditoastApi = generatedEditoastApi
8585
{
8686
id: extractEditoastIdFromPacedTrainId(pacedTrainId),
8787
infraId,
88-
exceptionKey,
88+
exceptionId,
8989
},
9090
{ subscribe: false }
9191
)

tests/tests/test_paced_train.py

Lines changed: 33 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,10 @@ def test_put_paced_train(
7272

7373

7474
def test_get_paced_train_with_exception_path(
75-
west_to_south_east_paced_train: Sequence[Any], small_infra: Infra, session: Session
75+
west_to_south_east_paced_train: Sequence[Any],
76+
small_infra: Infra,
77+
timetable_id: int,
78+
session: Session,
7679
):
7780
paced_train = west_to_south_east_paced_train[0]
7881
paced_train_id = paced_train["id"]
@@ -83,40 +86,44 @@ def test_get_paced_train_with_exception_path(
8386
).json()
8487

8588
# Add exception to the paced train
86-
exception = {
89+
exception_payload = {
8790
"key": "exception_key",
91+
"train_schedule_id": paced_train_id,
8892
"disabled": False,
89-
"path_and_schedule": {
90-
"power_restrictions": [],
91-
"schedule": [],
92-
"path": [
93-
{
94-
"id": "id1",
95-
"deleted": False,
96-
"location": {"track": "TA0", "offset": 470000},
97-
},
98-
{
99-
"id": "id2",
100-
"deleted": False,
101-
"location": {"track": "TG4", "offset": 1993000},
93+
"change_groups": {
94+
"path_and_schedule": {
95+
"power_restrictions": [],
96+
"schedule": [],
97+
"path": [
98+
{
99+
"id": "id1",
100+
"deleted": False,
101+
"location": {"track": "TA0", "offset": 470000},
102+
},
103+
{
104+
"id": "id2",
105+
"deleted": False,
106+
"location": {"track": "TG4", "offset": 1993000},
107+
},
108+
],
109+
"margins": {
110+
"boundaries": [],
111+
"values": ["5%"],
102112
},
103-
],
104-
"margins": {
105-
"boundaries": [],
106-
"values": ["5%"],
107113
},
114+
"initial_speed": {"value": 20.0},
108115
},
109-
"initial_speed": {"value": 20.0},
110116
}
111-
paced_train["paced"]["exceptions"] = [exception]
112-
update_response = session.put(
113-
f"{EDITOAST_URL}train_schedules/{paced_train_id}", json=paced_train
114-
)
115-
assert update_response.status_code == 204
117+
exception = session.post(
118+
f"{EDITOAST_URL}timetable/{timetable_id}/train_schedule_exception",
119+
json=exception_payload,
120+
).json()
121+
116122
# Get exception path
117123
exception_path_result = session.get(
118-
f"{EDITOAST_URL}train_schedules/{paced_train_id}/path?infra_id={small_infra.id}&exception_key=exception_key"
124+
f"{EDITOAST_URL}train_schedules/{paced_train_id}/path?infra_id={small_infra.id}&exception_id={exception['id']}"
119125
).json()
126+
120127
base_track_sections = [
121128
tsr["track_section"]
122129
for tsr in paced_train_path_result["path"]["track_section_ranges"]

0 commit comments

Comments
 (0)