109 lines
3.9 KiB
Rust
109 lines
3.9 KiB
Rust
use std::sync::Arc;
|
|
use axum::{
|
|
Json,
|
|
http::StatusCode,
|
|
extract::State,
|
|
};
|
|
use axum_core::response::IntoResponse;
|
|
use chrono::DateTime;
|
|
use serde::Deserialize;
|
|
use sqlx::{Error, PgPool};
|
|
use sqlx::postgres::PgQueryResult;
|
|
use crate::api::db_vendo_navigator::get_railcar_identifier_by_journey;
|
|
use crate::error::train_order_api_error::{CheckInError, ResolveTripNumberError};
|
|
use crate::model::app::AppState;
|
|
use crate::model::database::User;
|
|
use crate::model::travelynx::{CheckInReason, Train};
|
|
use crate::util::axum::UserBearerTokenExtractor;
|
|
|
|
#[derive(Debug, Deserialize)]
|
|
pub(crate) enum CheckIn {
|
|
Traewelling(crate::model::traewelling::CheckIn),
|
|
Travelynx(crate::model::travelynx::CheckIn),
|
|
}
|
|
|
|
#[axum::debug_handler]
|
|
pub(crate) async fn receive_travelynx(
|
|
State(app_state): State<AppState>,
|
|
UserBearerTokenExtractor(user): UserBearerTokenExtractor,
|
|
Json(body): Json<crate::model::travelynx::CheckIn>,
|
|
) -> impl IntoResponse {
|
|
receive_travelynx_checkin(body, user, app_state.db).await.into_response()
|
|
}
|
|
|
|
async fn receive_travelynx_checkin(
|
|
check_in: crate::model::travelynx::CheckIn,
|
|
user: User,
|
|
db: Arc<PgPool>
|
|
) -> impl IntoResponse {
|
|
match check_in.reason {
|
|
CheckInReason::CHECKIN => {
|
|
let railcar_identifier = get_railcar_identifier_by_journey(
|
|
check_in.status.train.train_type.unwrap(),
|
|
check_in.status.train.number.to_owned().unwrap().parse().unwrap(),
|
|
check_in.status.from_station.uic,
|
|
check_in.status.from_station.scheduled_time.unwrap()
|
|
)
|
|
.await
|
|
.map_err(|e| CheckInError::from(e))?;
|
|
let train_result = get_train_by_identifier(railcar_identifier as i32, db.clone())
|
|
.await;
|
|
let train = train_result
|
|
.map_err(|e| {
|
|
match e {
|
|
Error::RowNotFound => CheckInError::TrainNotFound,
|
|
e => CheckInError::from(ResolveTripNumberError::from(e))
|
|
}
|
|
})?;
|
|
println!("Train: {:?}", train);
|
|
let result = record_journey(user, train, check_in.status.from_station.scheduled_time.unwrap(), db)
|
|
.await
|
|
.map_err(|e| CheckInError::from(ResolveTripNumberError::from(e)))?;
|
|
println!("Journey recorded: {:?}", result);
|
|
let message = format!(
|
|
"Successfully checked into {} {} ({}), departing from station {} at {}",
|
|
check_in.status.train.train_type.unwrap(),
|
|
check_in.status.train.number.unwrap(),
|
|
railcar_identifier,
|
|
check_in.status.from_station.uic,
|
|
check_in.status.from_station.scheduled_time.unwrap()
|
|
);
|
|
Ok::<_, CheckInError>((
|
|
StatusCode::CREATED,
|
|
message
|
|
).into_response())
|
|
},
|
|
CheckInReason::UNDO => {
|
|
Ok::<_, CheckInError>((
|
|
StatusCode::OK,
|
|
"Checkin undone"
|
|
).into_response())
|
|
},
|
|
_ => Ok::<_, CheckInError>((
|
|
StatusCode::OK,
|
|
"Nothing to do!"
|
|
).into_response())
|
|
}
|
|
}
|
|
|
|
async fn get_train_by_identifier(identifier: i32, db: Arc<PgPool>) -> sqlx::Result<crate::model::database::Train> {
|
|
sqlx::query_as!(
|
|
crate::model::database::Train,
|
|
"SELECT * FROM triebzug WHERE tz_id = $1",
|
|
identifier
|
|
).fetch_one(db.as_ref()).await
|
|
}
|
|
|
|
async fn record_journey(
|
|
user: User,
|
|
train: crate::model::database::Train,
|
|
timestamp: usize,
|
|
db: Arc<PgPool>
|
|
) -> sqlx::Result<PgQueryResult> {
|
|
sqlx::query!(
|
|
"INSERT INTO checkins VALUES (gen_random_uuid(), $1, $2, $3, NULL)",
|
|
user.uuid,
|
|
train.uuid,
|
|
DateTime::from_timestamp(timestamp as i64, 0).unwrap().naive_utc()
|
|
).execute(db.as_ref()).await
|
|
} |