plc_control/crates/app_operation_system/src/service/station.rs

195 lines
5.1 KiB
Rust

use sqlx::PgPool;
use uuid::Uuid;
use crate::model::{Station, StationSignal};
pub async fn list_stations(
pool: &PgPool,
line_code: Option<&str>,
) -> Result<Vec<Station>, sqlx::Error> {
match line_code {
Some(line) => {
sqlx::query_as::<_, Station>(
r#"SELECT * FROM station WHERE line_code = $1 ORDER BY code"#,
)
.bind(line)
.fetch_all(pool)
.await
}
None => {
sqlx::query_as::<_, Station>(r#"SELECT * FROM station ORDER BY code"#)
.fetch_all(pool)
.await
}
}
}
pub async fn get_station_by_id(
pool: &PgPool,
station_id: Uuid,
) -> Result<Option<Station>, sqlx::Error> {
sqlx::query_as::<_, Station>(r#"SELECT * FROM station WHERE id = $1"#)
.bind(station_id)
.fetch_optional(pool)
.await
}
pub async fn get_station_by_code(
pool: &PgPool,
code: &str,
) -> Result<Option<Station>, sqlx::Error> {
sqlx::query_as::<_, Station>(r#"SELECT * FROM station WHERE code = $1"#)
.bind(code)
.fetch_optional(pool)
.await
}
pub struct CreateStationParams<'a> {
pub code: &'a str,
pub name: &'a str,
pub line_code: Option<&'a str>,
pub segment_code: Option<&'a str>,
pub station_type: &'a str,
pub enabled: bool,
pub description: Option<&'a str>,
}
pub async fn create_station(
pool: &PgPool,
params: CreateStationParams<'_>,
) -> Result<Uuid, sqlx::Error> {
let station_id = Uuid::new_v4();
sqlx::query(
r#"
INSERT INTO station (
id, code, name, line_code, segment_code, station_type, enabled, description
)
VALUES ($1, $2, $3, $4, $5, $6, $7, $8)
"#,
)
.bind(station_id)
.bind(params.code)
.bind(params.name)
.bind(params.line_code)
.bind(params.segment_code)
.bind(params.station_type)
.bind(params.enabled)
.bind(params.description)
.execute(pool)
.await?;
Ok(station_id)
}
pub struct UpdateStationParams<'a> {
pub code: Option<&'a str>,
pub name: Option<&'a str>,
pub line_code: Option<&'a str>,
pub segment_code: Option<&'a str>,
pub station_type: Option<&'a str>,
pub enabled: Option<bool>,
pub description: Option<&'a str>,
}
pub async fn update_station(
pool: &PgPool,
station_id: Uuid,
params: UpdateStationParams<'_>,
) -> Result<bool, sqlx::Error> {
let result = sqlx::query(
r#"
UPDATE station SET
code = COALESCE($2, code),
name = COALESCE($3, name),
line_code = COALESCE($4, line_code),
segment_code = COALESCE($5, segment_code),
station_type = COALESCE($6, station_type),
enabled = COALESCE($7, enabled),
description = COALESCE($8, description),
updated_at = NOW()
WHERE id = $1
"#,
)
.bind(station_id)
.bind(params.code)
.bind(params.name)
.bind(params.line_code)
.bind(params.segment_code)
.bind(params.station_type)
.bind(params.enabled)
.bind(params.description)
.execute(pool)
.await?;
Ok(result.rows_affected() > 0)
}
pub async fn delete_station(pool: &PgPool, station_id: Uuid) -> Result<bool, sqlx::Error> {
let result = sqlx::query(r#"DELETE FROM station WHERE id = $1"#)
.bind(station_id)
.execute(pool)
.await?;
Ok(result.rows_affected() > 0)
}
pub async fn list_station_signals(
pool: &PgPool,
station_id: Uuid,
) -> Result<Vec<StationSignal>, sqlx::Error> {
sqlx::query_as::<_, StationSignal>(
r#"SELECT * FROM station_signal WHERE station_id = $1 ORDER BY signal_role"#,
)
.bind(station_id)
.fetch_all(pool)
.await
}
pub struct UpsertStationSignalParams {
pub signal_role: String,
pub point_id: Option<Uuid>,
pub derived_from_role: Option<String>,
pub invert_value: bool,
}
pub async fn upsert_station_signal(
pool: &PgPool,
station_id: Uuid,
params: UpsertStationSignalParams,
) -> Result<StationSignal, sqlx::Error> {
sqlx::query_as::<_, StationSignal>(
r#"
INSERT INTO station_signal (
station_id, signal_role, point_id, derived_from_role, invert_value
)
VALUES ($1, $2, $3, $4, $5)
ON CONFLICT (station_id, signal_role) DO UPDATE SET
point_id = EXCLUDED.point_id,
derived_from_role = EXCLUDED.derived_from_role,
invert_value = EXCLUDED.invert_value,
updated_at = NOW()
RETURNING *
"#,
)
.bind(station_id)
.bind(&params.signal_role)
.bind(params.point_id)
.bind(&params.derived_from_role)
.bind(params.invert_value)
.fetch_one(pool)
.await
}
pub async fn delete_station_signal(
pool: &PgPool,
station_id: Uuid,
signal_role: &str,
) -> Result<bool, sqlx::Error> {
let result =
sqlx::query(r#"DELETE FROM station_signal WHERE station_id = $1 AND signal_role = $2"#)
.bind(station_id)
.bind(signal_role)
.execute(pool)
.await?;
Ok(result.rows_affected() > 0)
}