Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

editoast: change stdcm environment date type #9985

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
108 changes: 55 additions & 53 deletions editoast/src/client/stdcm_search_env_commands.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ use crate::CliError;
use crate::Exists;
use crate::Model;
use crate::Retrieve;
use chrono::DateTime;
use chrono::Duration;
use chrono::NaiveDateTime;
use chrono::Utc;
use clap::Args;
use clap::Subcommand;
use editoast_models::DbConnection;
Expand Down Expand Up @@ -62,10 +63,10 @@ pub struct SetSTDCMSearchEnvFromScenarioArgs {
pub work_schedule_group_id: Option<i64>,
/// If omitted, set to the earliest train start time in the timetable
#[arg(long)]
pub search_window_begin: Option<NaiveDateTime>,
pub search_window_begin: Option<DateTime<Utc>>,
/// If omitted, set to the latest train start time in the timetable plus one day
#[arg(long)]
pub search_window_end: Option<NaiveDateTime>,
pub search_window_end: Option<DateTime<Utc>>,
}

async fn set_stdcm_search_env_from_scenario(
Expand Down Expand Up @@ -126,10 +127,10 @@ pub struct SetSTDCMSearchEnvFromScratchArgs {
#[arg(long)]
/// If omitted, set to the earliest train start time in the timetable
#[arg(long)]
pub search_window_begin: Option<NaiveDateTime>,
pub search_window_begin: Option<DateTime<Utc>>,
/// If omitted, set to the latest train start time in the timetable plus one day
#[arg(long)]
pub search_window_end: Option<NaiveDateTime>,
pub search_window_end: Option<DateTime<Utc>>,
}

async fn set_stdcm_search_env_from_scratch(
Expand Down Expand Up @@ -178,10 +179,10 @@ async fn set_stdcm_search_env_from_scratch(

async fn resolve_search_window(
timetable_id: i64,
search_window_begin: Option<NaiveDateTime>,
search_window_end: Option<NaiveDateTime>,
search_window_begin: Option<DateTime<Utc>>,
search_window_end: Option<DateTime<Utc>>,
conn: &mut DbConnection,
) -> Result<(NaiveDateTime, NaiveDateTime), Box<dyn Error + Send + Sync>> {
) -> Result<(DateTime<Utc>, DateTime<Utc>), Box<dyn Error + Send + Sync>> {
let (begin, end) = if let (Some(begin), Some(end)) = (search_window_begin, search_window_end) {
(begin, end)
} else {
Expand All @@ -193,8 +194,8 @@ async fn resolve_search_window(
return Err(Box::new(CliError::new(1, error_msg)));
};

let begin = search_window_begin.unwrap_or(min.naive_utc());
let end = search_window_end.unwrap_or(max.naive_utc() + Duration::days(1));
let begin = search_window_begin.unwrap_or(*min);
let end = search_window_end.unwrap_or(*max + Duration::days(1));
(begin, end)
};

Expand Down Expand Up @@ -235,22 +236,23 @@ mod tests {
};

use super::*;
use chrono::NaiveDateTime;
use chrono::DateTime;
use chrono::Utc;
use editoast_models::{DbConnection, DbConnectionPoolV2};
use rstest::rstest;

fn make_naive_datetime(s: &str) -> NaiveDateTime {
NaiveDateTime::parse_from_str(s, "%Y-%m-%d %H:%M:%S").unwrap()
fn make_datetime(s: &str) -> DateTime<Utc> {
DateTime::parse_from_rfc3339(s).unwrap().to_utc()
}

async fn create_train_schedules_from_start_times(
start_times: Vec<NaiveDateTime>,
start_times: Vec<DateTime<Utc>>,
timetable_id: i64,
conn: &mut DbConnection,
) {
for start_time in start_times {
simple_train_schedule_changeset(timetable_id)
.start_time(start_time.and_utc())
.start_time(start_time)
.create(conn)
.await
.expect("Should be able to create train schedules");
Expand All @@ -261,45 +263,45 @@ mod tests {
#[case::both_none(
None,
None,
make_naive_datetime("2000-01-01 11:59:59"),
make_naive_datetime("2000-02-03 00:00:01")
make_datetime("2000-01-01 11:59:59Z"),
make_datetime("2000-02-03 00:00:01Z")
)]
#[case::begin_none(
None,
Some(make_naive_datetime("2000-02-01 00:00:00")),
make_naive_datetime("2000-01-01 11:59:59"),
make_naive_datetime("2000-02-01 00:00:00")
Some(make_datetime("2000-02-01 00:00:00Z")),
make_datetime("2000-01-01 11:59:59Z"),
make_datetime("2000-02-01 00:00:00Z")
)]
#[case::end_none(
Some(make_naive_datetime("2000-02-01 08:00:00")),
Some(make_datetime("2000-02-01 08:00:00Z")),
None,
make_naive_datetime("2000-02-01 08:00:00"),
make_naive_datetime("2000-02-03 00:00:01")
make_datetime("2000-02-01 08:00:00Z"),
make_datetime("2000-02-03 00:00:01Z")
)]
#[case::both_some(
Some(make_naive_datetime("2000-02-01 08:00:00")),
Some(make_naive_datetime("2000-05-22 09:00:50")),
make_naive_datetime("2000-02-01 08:00:00"),
make_naive_datetime("2000-05-22 09:00:50")
Some(make_datetime("2000-02-01 08:00:00Z")),
Some(make_datetime("2000-05-22 09:00:50Z")),
make_datetime("2000-02-01 08:00:00Z"),
make_datetime("2000-05-22 09:00:50Z")
)]
async fn test_resolve_search_window(
#[case] search_window_begin: Option<NaiveDateTime>,
#[case] search_window_end: Option<NaiveDateTime>,
#[case] expected_begin: NaiveDateTime,
#[case] expected_end: NaiveDateTime,
#[case] search_window_begin: Option<DateTime<Utc>>,
#[case] search_window_end: Option<DateTime<Utc>>,
#[case] expected_begin: DateTime<Utc>,
#[case] expected_end: DateTime<Utc>,
) {
let db_pool = DbConnectionPoolV2::for_tests();
let conn = &mut db_pool.get_ok();

let timetable = create_timetable(conn).await;

let start_times = vec![
make_naive_datetime("2000-01-01 12:00:00"),
make_naive_datetime("2000-02-02 00:00:00"),
make_naive_datetime("2000-01-01 11:59:59"), // earliest
make_naive_datetime("2000-01-15 08:59:59"),
make_naive_datetime("2000-02-02 00:00:01"), // latest
make_naive_datetime("2000-01-19 17:00:00"),
make_datetime("2000-01-01 12:00:00Z"),
make_datetime("2000-02-02 00:00:00Z"),
make_datetime("2000-01-01 11:59:59Z"), // earliest
make_datetime("2000-01-15 08:59:59Z"),
make_datetime("2000-02-02 00:00:01Z"), // latest
make_datetime("2000-01-19 17:00:00Z"),
];

create_train_schedules_from_start_times(start_times, timetable.id, conn).await;
Expand Down Expand Up @@ -327,23 +329,23 @@ mod tests {

#[rstest]
#[case::both_some(
Some(make_naive_datetime("2000-02-01 08:00:00")),
Some(make_naive_datetime("2000-02-01 00:00:00"))
Some(make_datetime("2000-02-01 08:00:00Z")),
Some(make_datetime("2000-02-01 00:00:00Z"))
)]
#[case::end_none(Some(make_naive_datetime("2000-03-01 00:00:00")), None)]
#[case::begin_none(None, Some(make_naive_datetime("2000-01-01 08:00:00")))]
#[case::end_none(Some(make_datetime("2000-03-01 00:00:00Z")), None)]
#[case::begin_none(None, Some(make_datetime("2000-01-01 08:00:00Z")))]
async fn test_resolve_search_window_incompatible_dates(
#[case] search_window_begin: Option<NaiveDateTime>,
#[case] search_window_end: Option<NaiveDateTime>,
#[case] search_window_begin: Option<DateTime<Utc>>,
#[case] search_window_end: Option<DateTime<Utc>>,
) {
let db_pool = DbConnectionPoolV2::for_tests();
let conn = &mut db_pool.get_ok();

let timetable = create_timetable(conn).await;

let start_times = vec![
make_naive_datetime("2000-01-01 12:00:00"),
make_naive_datetime("2000-02-02 00:00:01"),
make_datetime("2000-01-01 12:00:00Z"),
make_datetime("2000-02-02 00:00:01Z"),
];

create_train_schedules_from_start_times(start_times, timetable.id, conn).await;
Expand All @@ -366,8 +368,8 @@ mod tests {
let work_schedule_group = create_work_schedule_group(conn).await;

let start_times = vec![
make_naive_datetime("2000-01-01 12:00:00"),
make_naive_datetime("2000-02-02 08:00:00"),
make_datetime("2000-01-01 12:00:00Z"),
make_datetime("2000-02-02 08:00:00Z"),
];

create_train_schedules_from_start_times(
Expand All @@ -394,11 +396,11 @@ mod tests {

assert_eq!(
search_env.search_window_begin,
make_naive_datetime("2000-01-01 12:00:00")
make_datetime("2000-01-01 12:00:00Z")
);
assert_eq!(
search_env.search_window_end,
make_naive_datetime("2000-02-03 08:00:00")
make_datetime("2000-02-03 08:00:00Z")
);
}

Expand All @@ -413,8 +415,8 @@ mod tests {
let electrical_profile_set = create_electrical_profile_set(conn).await;

let start_times = vec![
make_naive_datetime("2000-01-01 12:00:00"),
make_naive_datetime("2000-02-02 08:00:00"),
make_datetime("2000-01-01 12:00:00Z"),
make_datetime("2000-02-02 08:00:00Z"),
];

create_train_schedules_from_start_times(start_times, timetable.id, conn).await;
Expand All @@ -438,11 +440,11 @@ mod tests {

assert_eq!(
search_env.search_window_begin,
make_naive_datetime("2000-01-01 12:00:00")
make_datetime("2000-01-01 12:00:00Z")
);
assert_eq!(
search_env.search_window_end,
make_naive_datetime("2000-02-03 08:00:00")
make_datetime("2000-02-03 08:00:00Z")
);
}
}
30 changes: 16 additions & 14 deletions editoast/src/models/stdcm_search_environment.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use chrono::NaiveDateTime;
use chrono::DateTime;
use chrono::Utc;
use diesel::ExpressionMethods;
use diesel::QueryDsl;
use diesel_async::RunQueryDsl;
Expand Down Expand Up @@ -28,8 +29,8 @@ pub struct StdcmSearchEnvironment {
#[serde(skip_serializing_if = "Option::is_none")]
pub work_schedule_group_id: Option<i64>,
pub timetable_id: i64,
pub search_window_begin: NaiveDateTime,
pub search_window_end: NaiveDateTime,
pub search_window_begin: DateTime<Utc>,
pub search_window_end: DateTime<Utc>,
#[schema(nullable = false)]
#[serde(skip_serializing_if = "Option::is_none")]
pub temporary_speed_limit_group_id: Option<i64>,
Expand Down Expand Up @@ -65,7 +66,8 @@ impl StdcmSearchEnvironmentChangeset {

#[cfg(test)]
pub mod tests {
use chrono::NaiveDate;
use chrono::TimeZone;
use chrono::Utc;
use pretty_assertions::assert_eq;
use rstest::rstest;

Expand Down Expand Up @@ -127,11 +129,11 @@ pub mod tests {
.work_schedule_group_id(Some(work_schedule_group.id))
.temporary_speed_limit_group_id(Some(temporary_speed_limit_group.id))
.timetable_id(timetable.id)
.search_window_begin(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap().into())
.search_window_end(NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().into());
.search_window_begin(Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap())
.search_window_end(Utc.with_ymd_and_hms(2024, 1, 15, 0, 0, 0).unwrap());

let begin = NaiveDate::from_ymd_opt(2024, 1, 16).unwrap().into();
let end = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap().into();
let begin = Utc.with_ymd_and_hms(2024, 1, 16, 0, 0, 0).unwrap();
let end = Utc.with_ymd_and_hms(2024, 1, 13, 0, 0, 0).unwrap();

let changeset_2 = changeset_1
.clone()
Expand Down Expand Up @@ -190,16 +192,16 @@ pub mod tests {
.work_schedule_group_id(Some(work_schedule_group.id))
.temporary_speed_limit_group_id(Some(temporary_speed_limit_group.id))
.timetable_id(timetable.id)
.search_window_begin(NaiveDate::from_ymd_opt(2024, 1, 1).unwrap().into())
.search_window_end(NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().into());
.search_window_begin(Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap())
.search_window_end(Utc.with_ymd_and_hms(2024, 1, 15, 0, 0, 0).unwrap());

let too_young = too_old
.clone()
.search_window_begin(NaiveDate::from_ymd_opt(2024, 1, 16).unwrap().into())
.search_window_end(NaiveDate::from_ymd_opt(2024, 1, 31).unwrap().into());
.search_window_begin(Utc.with_ymd_and_hms(2024, 1, 16, 0, 0, 0).unwrap())
.search_window_end(Utc.with_ymd_and_hms(2024, 1, 31, 0, 0, 0).unwrap());

let begin = NaiveDate::from_ymd_opt(2024, 1, 7).unwrap().into();
let end = NaiveDate::from_ymd_opt(2024, 1, 31).unwrap().into();
let begin = Utc.with_ymd_and_hms(2024, 1, 7, 0, 0, 0).unwrap();
let end = Utc.with_ymd_and_hms(2024, 1, 31, 0, 0, 0).unwrap();

let the_best = too_old
.clone()
Expand Down
22 changes: 12 additions & 10 deletions editoast/src/views/stdcm_search_environment.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ use axum::http::StatusCode;
use axum::response::IntoResponse;
use axum::response::Response;
use axum::Extension;
use chrono::NaiveDateTime;
use chrono::DateTime;
use chrono::Utc;
use editoast_authz::BuiltinRole;
use editoast_models::DbConnectionPoolV2;
use serde::de::Error as SerdeError;
Expand Down Expand Up @@ -42,8 +43,8 @@ struct StdcmSearchEnvironmentCreateForm {
work_schedule_group_id: Option<i64>,
temporary_speed_limit_group_id: Option<i64>,
timetable_id: i64,
search_window_begin: NaiveDateTime, // TODO: move to DateTime<Utc>
search_window_end: NaiveDateTime,
search_window_begin: DateTime<Utc>,
search_window_end: DateTime<Utc>,
}

impl<'de> Deserialize<'de> for StdcmSearchEnvironmentCreateForm {
Expand All @@ -59,8 +60,8 @@ impl<'de> Deserialize<'de> for StdcmSearchEnvironmentCreateForm {
work_schedule_group_id: Option<i64>,
temporary_speed_limit_group_id: Option<i64>,
timetable_id: i64,
search_window_begin: NaiveDateTime,
search_window_end: NaiveDateTime,
search_window_begin: DateTime<Utc>,
search_window_end: DateTime<Utc>,
}
let internal = Internal::deserialize(deserializer)?;

Expand Down Expand Up @@ -156,7 +157,8 @@ async fn retrieve_latest(
#[cfg(test)]
pub mod tests {
use axum::http::StatusCode;
use chrono::NaiveDate;
use chrono::TimeZone;
use chrono::Utc;
use pretty_assertions::assert_eq;
use rstest::rstest;

Expand Down Expand Up @@ -185,8 +187,8 @@ pub mod tests {
work_schedule_group_id: Some(work_schedule_group.id),
temporary_speed_limit_group_id: Some(temporary_speed_limit_group.id),
timetable_id: timetable.id,
search_window_begin: NaiveDate::from_ymd_opt(2024, 1, 1).unwrap().into(),
search_window_end: NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().into(),
search_window_begin: Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap(),
search_window_end: Utc.with_ymd_and_hms(2024, 1, 15, 0, 0, 0).unwrap(),
};

let request = app.post("/stdcm/search_environment").json(&form);
Expand Down Expand Up @@ -224,8 +226,8 @@ pub mod tests {
electrical_profile_set,
) = stdcm_search_env_fixtures(&mut pool.get_ok()).await;

let begin = NaiveDate::from_ymd_opt(2024, 1, 1).unwrap().into();
let end = NaiveDate::from_ymd_opt(2024, 1, 15).unwrap().into();
let begin = Utc.with_ymd_and_hms(2024, 1, 1, 0, 0, 0).unwrap();
let end = Utc.with_ymd_and_hms(2024, 1, 15, 0, 0, 0).unwrap();

let _ = StdcmSearchEnvironment::changeset()
.infra_id(infra.id)
Expand Down
2 changes: 1 addition & 1 deletion front/src/applications/stdcm/hooks/useStdcmEnv.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ export default function useStdcmEnvironment() {
workScheduleGroupId: data.work_schedule_group_id,
temporarySpeedLimitGroupId: data.temporary_speed_limit_group_id,
searchDatetimeWindow: {
begin: new Date(`${data.search_window_begin}Z`), // TODO: Remove this temporary fix when editoast returns the date in UTC
begin: new Date(data.search_window_begin),
end: new Date(data.search_window_end),
},
})
Expand Down
2 changes: 1 addition & 1 deletion front/tests/utils/api-setup.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,7 +256,7 @@ export async function getStdcmEnvironment(): Promise<StdcmSearchEnvironment | nu
*/
export async function setStdcmEnvironment(stdcmEnvironment: StdcmSearchEnvironment): Promise<void> {
// Remove the `id` field to match the StdcmSearchEnvironmentCreateForm schema
const { id, ...stdcmEnvironmentWithoutId } = stdcmEnvironment;
const { id: _id, ...stdcmEnvironmentWithoutId } = stdcmEnvironment;
await postApiRequest(
'/api/stdcm/search_environment',
stdcmEnvironmentWithoutId,
Expand Down
Loading
Loading