Skip to content

Commit 446c793

Browse files
committed
editoat: add migrations and models for train schedule v2
1 parent 1a11992 commit 446c793

File tree

7 files changed

+287
-1
lines changed

7 files changed

+287
-1
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
DROP TABLE scenariov2;
2+
DROP TABLE trainschedulev2;
3+
DROP TABLE timetablev2;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
CREATE TABLE timetablev2 (
2+
id int8 PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
3+
electrical_profile_set_id int8 NULL REFERENCES electrical_profile_set(id) ON DELETE CASCADE
4+
);
5+
CREATE TABLE scenariov2 (
6+
id int8 PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
7+
infra_id int8 NOT NULL REFERENCES infra(id) ON DELETE CASCADE DEFERRABLE INITIALLY DEFERRED,
8+
name varchar(128) NOT NULL,
9+
description varchar(1024) NOT NULL,
10+
creation_date timestamptz NOT NULL,
11+
last_modification timestamptz NOT NULL,
12+
tags text [] NOT NULL,
13+
timetable_id int8 NOT NULL UNIQUE REFERENCES timetablev2(id) DEFERRABLE INITIALLY DEFERRED,
14+
study_id int8 NOT NULL REFERENCES study(id) ON DELETE CASCADE
15+
);
16+
CREATE TABLE trainschedulev2 (
17+
id int8 PRIMARY KEY GENERATED BY DEFAULT AS IDENTITY,
18+
train_name varchar(128) NOT NULL,
19+
labels text [] NOT NULL,
20+
rolling_stock_name varchar(128) NOT NULL,
21+
timetable_id int8 NOT NULL UNIQUE REFERENCES timetablev2(id) DEFERRABLE INITIALLY DEFERRED,
22+
start_time timestamptz NOT NULL,
23+
schedule jsonb NOT NULL,
24+
margins jsonb NOT NULL,
25+
initial_speed float8 NOT NULL,
26+
comfort smallint NOT NULL,
27+
path jsonb NOT NULL,
28+
constraint_distribution smallint NOT NULL,
29+
speed_limit_tag varchar(128),
30+
power_restrictions jsonb NOT NULL,
31+
options jsonb NOT NULL
32+
);

editoast/src/modelsv2/mod.rs

+4-1
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
pub mod documents;
22
pub mod infra_objects;
33
pub mod railjson;
4-
4+
pub mod scenario;
5+
pub mod timetable;
6+
pub mod trainschedule;
57
pub use documents::Document;
68
pub use infra_objects::*;
9+
pub use timetable::TimetableV2;
710

811
use async_trait::async_trait;
912
use diesel::{pg::Pg, result::Error::NotFound, AsChangeset, QueryableByName};

editoast/src/modelsv2/scenario.rs

+105
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
use crate::error::Result;
2+
use crate::models::List;
3+
use crate::models::Ordering;
4+
use crate::modelsv2::Model;
5+
use crate::modelsv2::Row;
6+
use crate::views::pagination::Paginate;
7+
use crate::views::pagination::PaginatedResponse;
8+
use async_trait::async_trait;
9+
use chrono::NaiveDateTime;
10+
use diesel::sql_query;
11+
use diesel::sql_types::{BigInt, Text};
12+
use diesel::{ExpressionMethods, QueryDsl};
13+
use diesel_async::{AsyncPgConnection as PgConnection, RunQueryDsl};
14+
use editoast_derive::ModelV2;
15+
use serde_derive::{Deserialize, Serialize};
16+
17+
#[derive(Debug, Clone, ModelV2, Deserialize, Serialize)]
18+
#[model(table = crate::tables::scenariov2)]
19+
#[model(changeset(public))]
20+
pub struct ScenarioV2 {
21+
pub id: i64,
22+
pub infra_id: i64,
23+
pub name: String,
24+
pub description: String,
25+
pub creation_date: NaiveDateTime,
26+
pub last_modification: NaiveDateTime,
27+
pub tags: Vec<Option<String>>,
28+
pub timetable_id: i64,
29+
pub study_id: i64,
30+
}
31+
32+
#[derive(Debug, Clone, Deserialize, Serialize, QueryableByName)]
33+
pub struct ScenarioV2WithDetails {
34+
#[serde(flatten)]
35+
#[diesel(embed)]
36+
pub scenario: ScenarioV2,
37+
#[diesel(sql_type = Text)]
38+
pub infra_name: String,
39+
#[diesel(sql_type = BigInt)]
40+
pub trains_count: i64,
41+
}
42+
43+
impl ScenarioV2 {
44+
pub async fn with_details_conn(self, conn: &mut PgConnection) -> Result<ScenarioV2WithDetails> {
45+
use crate::tables::infra::dsl as infra_dsl;
46+
use crate::tables::trainschedulev2::dsl::*;
47+
48+
let infra_name = infra_dsl::infra
49+
.filter(infra_dsl::id.eq(self.infra_id))
50+
.select(infra_dsl::name)
51+
.first::<String>(conn)
52+
.await?;
53+
54+
let trains_count = trainschedulev2
55+
.filter(timetable_id.eq(self.timetable_id))
56+
.count()
57+
.get_result(conn)
58+
.await?;
59+
60+
Ok(ScenarioV2WithDetails {
61+
scenario: self,
62+
infra_name,
63+
trains_count,
64+
})
65+
}
66+
}
67+
68+
#[async_trait]
69+
impl List<(i64, Ordering)> for ScenarioV2 {
70+
/// List all scenarios with the number of trains.
71+
/// This functions takes a study_id to filter scenarios.
72+
async fn list_conn(
73+
conn: &mut PgConnection,
74+
page: i64,
75+
page_size: i64,
76+
params: (i64, Ordering),
77+
) -> Result<PaginatedResponse<Self>> {
78+
let study_id = params.0;
79+
let ordering = params.1.to_sql();
80+
let scenario_rows = sql_query(format!("WITH scenarios_with_train_counts AS (
81+
SELECT t.*, COUNT(train_schedule.id) as trains_count
82+
FROM scenariov2 as t
83+
LEFT JOIN train_schedule ON t.timetable_id = train_schedule.timetable_id WHERE t.study_id = $1
84+
GROUP BY t.id ORDER BY {ordering}
85+
)
86+
SELECT scenarios_with_train_counts.*, infra.name as infra_name
87+
FROM scenarios_with_train_counts
88+
JOIN infra ON infra.id = infra_id"))
89+
.bind::<BigInt, _>(study_id)
90+
.paginate(page, page_size)
91+
.load_and_count::<Row<ScenarioV2>>(conn).await?;
92+
93+
let results: Vec<ScenarioV2> = scenario_rows
94+
.results
95+
.into_iter()
96+
.map(Self::from_row)
97+
.collect();
98+
Ok(PaginatedResponse {
99+
count: scenario_rows.count,
100+
previous: scenario_rows.previous,
101+
next: scenario_rows.next,
102+
results,
103+
})
104+
}
105+
}

editoast/src/modelsv2/timetable.rs

+50
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
use crate::diesel::query_dsl::methods::DistinctDsl;
2+
use crate::error::Result;
3+
use crate::models::List;
4+
use crate::models::NoParams;
5+
use crate::modelsv2::Model;
6+
use crate::modelsv2::Row;
7+
use crate::tables::timetablev2::dsl;
8+
use crate::views::pagination::Paginate;
9+
use crate::views::pagination::PaginatedResponse;
10+
use async_trait::async_trait;
11+
use diesel_async::AsyncPgConnection as PgConnection;
12+
use editoast_derive::ModelV2;
13+
use serde::{Deserialize, Serialize};
14+
15+
#[derive(Debug, Default, Clone, ModelV2, Serialize, Deserialize)]
16+
#[model(table = crate::tables::timetablev2)]
17+
#[model(changeset(public))]
18+
pub struct TimetableV2 {
19+
pub id: i64,
20+
pub electrical_profile_set_id: Option<i64>,
21+
}
22+
23+
#[async_trait]
24+
impl List<NoParams> for TimetableV2 {
25+
async fn list_conn(
26+
conn: &mut PgConnection,
27+
page: i64,
28+
page_size: i64,
29+
_: NoParams,
30+
) -> Result<PaginatedResponse<Self>> {
31+
let timetable_rows = dsl::timetablev2
32+
.distinct()
33+
.paginate(page, page_size)
34+
.load_and_count::<Row<TimetableV2>>(conn)
35+
.await?;
36+
37+
let results: Vec<TimetableV2> = timetable_rows
38+
.results
39+
.into_iter()
40+
.map(Self::from_row)
41+
.collect();
42+
43+
Ok(PaginatedResponse {
44+
count: timetable_rows.count,
45+
previous: timetable_rows.previous,
46+
next: timetable_rows.next,
47+
results,
48+
})
49+
}
50+
}
+30
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
use crate::schema::v2::trainschedule::{
2+
Comfort, Distribution, Margins, PathItem, PowerRestrictionItem, ScheduleItem,
3+
TrainScheduleOptions,
4+
};
5+
use crate::DieselJson;
6+
use chrono::{DateTime, Utc};
7+
use editoast_derive::ModelV2;
8+
9+
#[derive(Debug, Default, Clone, ModelV2)]
10+
#[model(table = crate::tables::trainschedulev2)]
11+
#[model(changeset(public))]
12+
pub struct TrainSchedule {
13+
pub id: i64,
14+
pub train_name: String,
15+
pub labels: Vec<Option<String>>,
16+
pub rolling_stock_name: String,
17+
pub timetable_id: i64,
18+
pub start_time: DateTime<Utc>,
19+
pub schedule: DieselJson<Vec<ScheduleItem>>,
20+
pub margins: DieselJson<Margins>,
21+
pub initial_speed: f64,
22+
#[model(to_enum)]
23+
pub comfort: Comfort,
24+
pub path: DieselJson<Vec<PathItem>>,
25+
#[model(to_enum)]
26+
pub constraint_distribution: Distribution,
27+
pub speed_limit_tag: Option<String>,
28+
pub power_restrictions: DieselJson<Vec<PowerRestrictionItem>>,
29+
pub options: DieselJson<TrainScheduleOptions>,
30+
}

editoast/src/tables.rs

+63
Original file line numberDiff line numberDiff line change
@@ -490,6 +490,25 @@ diesel::table! {
490490
}
491491
}
492492

493+
diesel::table! {
494+
use diesel::sql_types::*;
495+
use postgis_diesel::sql_types::*;
496+
497+
scenariov2 (id) {
498+
id -> Int8,
499+
infra_id -> Int8,
500+
#[max_length = 128]
501+
name -> Varchar,
502+
#[max_length = 1024]
503+
description -> Varchar,
504+
creation_date -> Timestamptz,
505+
last_modification -> Timestamptz,
506+
tags -> Array<Nullable<Text>>,
507+
timetable_id -> Int8,
508+
study_id -> Int8,
509+
}
510+
}
511+
493512
diesel::table! {
494513
use diesel::sql_types::*;
495514
use postgis_diesel::sql_types::*;
@@ -633,6 +652,16 @@ diesel::table! {
633652
}
634653
}
635654

655+
diesel::table! {
656+
use diesel::sql_types::*;
657+
use postgis_diesel::sql_types::*;
658+
659+
timetablev2 (id) {
660+
id -> Int8,
661+
electrical_profile_set_id -> Nullable<Int8>,
662+
}
663+
}
664+
636665
diesel::table! {
637666
use diesel::sql_types::*;
638667
use postgis_diesel::sql_types::*;
@@ -661,6 +690,32 @@ diesel::table! {
661690
}
662691
}
663692

693+
diesel::table! {
694+
use diesel::sql_types::*;
695+
use postgis_diesel::sql_types::*;
696+
697+
trainschedulev2 (id) {
698+
id -> Int8,
699+
#[max_length = 128]
700+
train_name -> Varchar,
701+
labels -> Array<Nullable<Text>>,
702+
#[max_length = 128]
703+
rolling_stock_name -> Varchar,
704+
timetable_id -> Int8,
705+
start_time -> Timestamptz,
706+
schedule -> Jsonb,
707+
margins -> Jsonb,
708+
initial_speed -> Float8,
709+
comfort -> Int2,
710+
path -> Jsonb,
711+
constraint_distribution -> Int2,
712+
#[max_length = 128]
713+
speed_limit_tag -> Nullable<Varchar>,
714+
power_restrictions -> Jsonb,
715+
options -> Jsonb,
716+
}
717+
}
718+
664719
diesel::joinable!(infra_layer_buffer_stop -> infra (infra_id));
665720
diesel::joinable!(infra_layer_detector -> infra (infra_id));
666721
diesel::joinable!(infra_layer_electrification -> infra (infra_id));
@@ -694,16 +749,21 @@ diesel::joinable!(scenario -> electrical_profile_set (electrical_profile_set_id)
694749
diesel::joinable!(scenario -> infra (infra_id));
695750
diesel::joinable!(scenario -> study (study_id));
696751
diesel::joinable!(scenario -> timetable (timetable_id));
752+
diesel::joinable!(scenariov2 -> infra (infra_id));
753+
diesel::joinable!(scenariov2 -> study (study_id));
754+
diesel::joinable!(scenariov2 -> timetablev2 (timetable_id));
697755
diesel::joinable!(search_operational_point -> infra_object_operational_point (id));
698756
diesel::joinable!(search_project -> project (id));
699757
diesel::joinable!(search_scenario -> scenario (id));
700758
diesel::joinable!(search_signal -> infra_object_signal (id));
701759
diesel::joinable!(search_study -> study (id));
702760
diesel::joinable!(simulation_output -> train_schedule (train_schedule_id));
703761
diesel::joinable!(study -> project (project_id));
762+
diesel::joinable!(timetablev2 -> electrical_profile_set (electrical_profile_set_id));
704763
diesel::joinable!(train_schedule -> pathfinding (path_id));
705764
diesel::joinable!(train_schedule -> rolling_stock (rolling_stock_id));
706765
diesel::joinable!(train_schedule -> timetable (timetable_id));
766+
diesel::joinable!(trainschedulev2 -> timetablev2 (timetable_id));
707767

708768
diesel::allow_tables_to_appear_in_same_query!(
709769
document,
@@ -738,6 +798,7 @@ diesel::allow_tables_to_appear_in_same_query!(
738798
rolling_stock_livery,
739799
rolling_stock_separate_image,
740800
scenario,
801+
scenariov2,
741802
search_operational_point,
742803
search_project,
743804
search_scenario,
@@ -747,5 +808,7 @@ diesel::allow_tables_to_appear_in_same_query!(
747808
simulation_output,
748809
study,
749810
timetable,
811+
timetablev2,
750812
train_schedule,
813+
trainschedulev2,
751814
);

0 commit comments

Comments
 (0)