refactor(sort): order units and equipment by code

This commit is contained in:
caoqianming 2026-03-26 12:57:01 +08:00
parent ad4b0c0680
commit 86e651d9ca
2 changed files with 91 additions and 31 deletions

View File

@ -2,6 +2,14 @@ use crate::model::{ControlUnit, EventRecord};
use sqlx::{PgPool, QueryBuilder, Row}; use sqlx::{PgPool, QueryBuilder, Row};
use uuid::Uuid; use uuid::Uuid;
fn unit_order_clause() -> &'static str {
"code"
}
fn equipment_order_clause_with_unit() -> &'static str {
"unit_id, code"
}
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct EquipmentRolePoint { pub struct EquipmentRolePoint {
pub point_id: Uuid, pub point_id: Uuid,
@ -35,31 +43,36 @@ pub async fn get_units_paginated(
page_size: i32, page_size: i32,
offset: u32, offset: u32,
) -> Result<Vec<ControlUnit>, sqlx::Error> { ) -> Result<Vec<ControlUnit>, sqlx::Error> {
let unit_order = unit_order_clause();
match keyword { match keyword {
Some(keyword) => { Some(keyword) => {
let like = format!("%{}%", keyword); let like = format!("%{}%", keyword);
if page_size == -1 { if page_size == -1 {
sqlx::query_as::<_, ControlUnit>( let sql = format!(
r#" r#"
SELECT * SELECT *
FROM unit FROM unit
WHERE code ILIKE $1 OR name ILIKE $1 WHERE code ILIKE $1 OR name ILIKE $1
ORDER BY created_at ORDER BY {}
"#, "#,
) unit_order
);
sqlx::query_as::<_, ControlUnit>(&sql)
.bind(like) .bind(like)
.fetch_all(pool) .fetch_all(pool)
.await .await
} else { } else {
sqlx::query_as::<_, ControlUnit>( let sql = format!(
r#" r#"
SELECT * SELECT *
FROM unit FROM unit
WHERE code ILIKE $1 OR name ILIKE $1 WHERE code ILIKE $1 OR name ILIKE $1
ORDER BY created_at ORDER BY {}
LIMIT $2 OFFSET $3 LIMIT $2 OFFSET $3
"#, "#,
) unit_order
);
sqlx::query_as::<_, ControlUnit>(&sql)
.bind(like) .bind(like)
.bind(page_size as i64) .bind(page_size as i64)
.bind(offset as i64) .bind(offset as i64)
@ -69,18 +82,21 @@ pub async fn get_units_paginated(
} }
None => { None => {
if page_size == -1 { if page_size == -1 {
sqlx::query_as::<_, ControlUnit>(r#"SELECT * FROM unit ORDER BY created_at"#) let sql = format!("SELECT * FROM unit ORDER BY {}", unit_order);
sqlx::query_as::<_, ControlUnit>(&sql)
.fetch_all(pool) .fetch_all(pool)
.await .await
} else { } else {
sqlx::query_as::<_, ControlUnit>( let sql = format!(
r#" r#"
SELECT * SELECT *
FROM unit FROM unit
ORDER BY created_at ORDER BY {}
LIMIT $1 OFFSET $2 LIMIT $1 OFFSET $2
"#, "#,
) unit_order
);
sqlx::query_as::<_, ControlUnit>(&sql)
.bind(page_size as i64) .bind(page_size as i64)
.bind(offset as i64) .bind(offset as i64)
.fetch_all(pool) .fetch_all(pool)
@ -309,9 +325,11 @@ pub async fn get_events_paginated(
} }
pub async fn get_all_enabled_units(pool: &PgPool) -> Result<Vec<ControlUnit>, sqlx::Error> { pub async fn get_all_enabled_units(pool: &PgPool) -> Result<Vec<ControlUnit>, sqlx::Error> {
sqlx::query_as::<_, ControlUnit>( let sql = format!(
r#"SELECT * FROM unit WHERE enabled = TRUE ORDER BY created_at"#, "SELECT * FROM unit WHERE enabled = TRUE ORDER BY {}",
) unit_order_clause()
);
sqlx::query_as::<_, ControlUnit>(&sql)
.fetch_all(pool) .fetch_all(pool)
.await .await
} }
@ -323,9 +341,11 @@ pub async fn get_equipment_by_unit_ids(
if unit_ids.is_empty() { if unit_ids.is_empty() {
return Ok(vec![]); return Ok(vec![]);
} }
sqlx::query_as::<_, crate::model::Equipment>( let sql = format!(
r#"SELECT * FROM equipment WHERE unit_id = ANY($1) ORDER BY unit_id, created_at"#, "SELECT * FROM equipment WHERE unit_id = ANY($1) ORDER BY {}",
) equipment_order_clause_with_unit()
);
sqlx::query_as::<_, crate::model::Equipment>(&sql)
.bind(unit_ids) .bind(unit_ids)
.fetch_all(pool) .fetch_all(pool)
.await .await
@ -335,9 +355,11 @@ pub async fn get_equipment_by_unit_id(
pool: &PgPool, pool: &PgPool,
unit_id: Uuid, unit_id: Uuid,
) -> Result<Vec<crate::model::Equipment>, sqlx::Error> { ) -> Result<Vec<crate::model::Equipment>, sqlx::Error> {
sqlx::query_as::<_, crate::model::Equipment>( let sql = format!(
r#"SELECT * FROM equipment WHERE unit_id = $1 ORDER BY created_at"#, "SELECT * FROM equipment WHERE unit_id = $1 ORDER BY {}",
) unit_order_clause()
);
sqlx::query_as::<_, crate::model::Equipment>(&sql)
.bind(unit_id) .bind(unit_id)
.fetch_all(pool) .fetch_all(pool)
.await .await
@ -395,6 +417,21 @@ pub async fn get_signal_role_points_batch(
.collect()) .collect())
} }
#[cfg(test)]
mod tests {
use super::{equipment_order_clause_with_unit, unit_order_clause};
#[test]
fn unit_ordering_defaults_to_code() {
assert_eq!(unit_order_clause(), "code");
}
#[test]
fn unit_equipment_ordering_uses_code_within_unit() {
assert_eq!(equipment_order_clause_with_unit(), "unit_id, code");
}
}
pub async fn get_equipment_role_points( pub async fn get_equipment_role_points(
pool: &PgPool, pool: &PgPool,
equipment_id: Uuid, equipment_id: Uuid,

View File

@ -5,6 +5,10 @@ use crate::{
use sqlx::{query_as, PgPool, Row}; use sqlx::{query_as, PgPool, Row};
use uuid::Uuid; use uuid::Uuid;
fn equipment_order_clause() -> &'static str {
"e.code"
}
pub async fn get_points_by_equipment_id( pub async fn get_points_by_equipment_id(
pool: &PgPool, pool: &PgPool,
equipment_id: uuid::Uuid, equipment_id: uuid::Uuid,
@ -49,11 +53,12 @@ pub async fn get_equipment_paginated(
page_size: i32, page_size: i32,
offset: u32, offset: u32,
) -> Result<Vec<EquipmentListItem>, sqlx::Error> { ) -> Result<Vec<EquipmentListItem>, sqlx::Error> {
let equipment_order = equipment_order_clause();
let rows = match keyword { let rows = match keyword {
Some(keyword) => { Some(keyword) => {
let like = format!("%{}%", keyword); let like = format!("%{}%", keyword);
if page_size == -1 { if page_size == -1 {
sqlx::query( let sql = format!(
r#" r#"
SELECT SELECT
e.*, e.*,
@ -62,14 +67,16 @@ pub async fn get_equipment_paginated(
LEFT JOIN point p ON p.equipment_id = e.id LEFT JOIN point p ON p.equipment_id = e.id
WHERE e.code ILIKE $1 OR e.name ILIKE $1 WHERE e.code ILIKE $1 OR e.name ILIKE $1
GROUP BY e.id GROUP BY e.id
ORDER BY e.created_at ORDER BY {}
"#, "#,
) equipment_order
);
sqlx::query(&sql)
.bind(like) .bind(like)
.fetch_all(pool) .fetch_all(pool)
.await? .await?
} else { } else {
sqlx::query( let sql = format!(
r#" r#"
SELECT SELECT
e.*, e.*,
@ -78,10 +85,12 @@ pub async fn get_equipment_paginated(
LEFT JOIN point p ON p.equipment_id = e.id LEFT JOIN point p ON p.equipment_id = e.id
WHERE e.code ILIKE $1 OR e.name ILIKE $1 WHERE e.code ILIKE $1 OR e.name ILIKE $1
GROUP BY e.id GROUP BY e.id
ORDER BY e.created_at ORDER BY {}
LIMIT $2 OFFSET $3 LIMIT $2 OFFSET $3
"#, "#,
) equipment_order
);
sqlx::query(&sql)
.bind(like) .bind(like)
.bind(page_size as i64) .bind(page_size as i64)
.bind(offset as i64) .bind(offset as i64)
@ -91,7 +100,7 @@ pub async fn get_equipment_paginated(
} }
None => { None => {
if page_size == -1 { if page_size == -1 {
sqlx::query( let sql = format!(
r#" r#"
SELECT SELECT
e.*, e.*,
@ -99,13 +108,15 @@ pub async fn get_equipment_paginated(
FROM equipment e FROM equipment e
LEFT JOIN point p ON p.equipment_id = e.id LEFT JOIN point p ON p.equipment_id = e.id
GROUP BY e.id GROUP BY e.id
ORDER BY e.created_at ORDER BY {}
"#, "#,
) equipment_order
);
sqlx::query(&sql)
.fetch_all(pool) .fetch_all(pool)
.await? .await?
} else { } else {
sqlx::query( let sql = format!(
r#" r#"
SELECT SELECT
e.*, e.*,
@ -113,10 +124,12 @@ pub async fn get_equipment_paginated(
FROM equipment e FROM equipment e
LEFT JOIN point p ON p.equipment_id = e.id LEFT JOIN point p ON p.equipment_id = e.id
GROUP BY e.id GROUP BY e.id
ORDER BY e.created_at ORDER BY {}
LIMIT $1 OFFSET $2 LIMIT $1 OFFSET $2
"#, "#,
) equipment_order
);
sqlx::query(&sql)
.bind(page_size as i64) .bind(page_size as i64)
.bind(offset as i64) .bind(offset as i64)
.fetch_all(pool) .fetch_all(pool)
@ -284,3 +297,13 @@ pub async fn batch_set_equipment_unit(
Ok(result.rows_affected()) Ok(result.rows_affected())
} }
#[cfg(test)]
mod tests {
use super::equipment_order_clause;
#[test]
fn equipment_ordering_defaults_to_code() {
assert_eq!(equipment_order_clause(), "e.code");
}
}