175 lines
4.2 KiB
Rust
175 lines
4.2 KiB
Rust
use crate::domain::models::Column;
|
|
use common_telemetry::AppError;
|
|
use sqlx::PgPool;
|
|
use uuid::Uuid;
|
|
|
|
pub async fn create_column(
|
|
pool: &PgPool,
|
|
tenant_id: Uuid,
|
|
name: String,
|
|
slug: String,
|
|
description: Option<String>,
|
|
parent_id: Option<Uuid>,
|
|
sort_order: i32,
|
|
) -> Result<Column, AppError> {
|
|
let column = sqlx::query_as::<_, Column>(
|
|
r#"
|
|
INSERT INTO cms_columns (tenant_id, name, slug, description, parent_id, sort_order)
|
|
VALUES ($1, $2, $3, $4, $5, $6)
|
|
RETURNING tenant_id, id, name, slug, description, parent_id, sort_order, created_at, updated_at
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(name)
|
|
.bind(slug)
|
|
.bind(description)
|
|
.bind(parent_id)
|
|
.bind(sort_order)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
Ok(column)
|
|
}
|
|
|
|
pub async fn get_column(pool: &PgPool, tenant_id: Uuid, id: Uuid) -> Result<Column, AppError> {
|
|
let column = sqlx::query_as::<_, Column>(
|
|
r#"
|
|
SELECT tenant_id, id, name, slug, description, parent_id, sort_order, created_at, updated_at
|
|
FROM cms_columns
|
|
WHERE tenant_id = $1 AND id = $2
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(id)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
Ok(column)
|
|
}
|
|
|
|
pub async fn update_column(
|
|
pool: &PgPool,
|
|
tenant_id: Uuid,
|
|
id: Uuid,
|
|
name: Option<String>,
|
|
slug: Option<String>,
|
|
description: Option<Option<String>>,
|
|
parent_id: Option<Option<Uuid>>,
|
|
sort_order: Option<i32>,
|
|
) -> Result<Column, AppError> {
|
|
let column = sqlx::query_as::<_, Column>(
|
|
r#"
|
|
UPDATE cms_columns
|
|
SET
|
|
name = COALESCE($3, name),
|
|
slug = COALESCE($4, slug),
|
|
description = COALESCE($5, description),
|
|
parent_id = COALESCE($6, parent_id),
|
|
sort_order = COALESCE($7, sort_order),
|
|
updated_at = now()
|
|
WHERE tenant_id = $1 AND id = $2
|
|
RETURNING tenant_id, id, name, slug, description, parent_id, sort_order, created_at, updated_at
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(id)
|
|
.bind(name)
|
|
.bind(slug)
|
|
.bind(description)
|
|
.bind(parent_id)
|
|
.bind(sort_order)
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
Ok(column)
|
|
}
|
|
|
|
pub async fn delete_column(pool: &PgPool, tenant_id: Uuid, id: Uuid) -> Result<(), AppError> {
|
|
let res = sqlx::query(
|
|
r#"
|
|
DELETE FROM cms_columns
|
|
WHERE tenant_id = $1 AND id = $2
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(id)
|
|
.execute(pool)
|
|
.await?;
|
|
|
|
if res.rows_affected() == 0 {
|
|
return Err(AppError::NotFound("column:not_found".into()));
|
|
}
|
|
Ok(())
|
|
}
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub struct ListColumnsQuery {
|
|
pub page: u32,
|
|
pub page_size: u32,
|
|
pub search: Option<String>,
|
|
pub parent_id: Option<Uuid>,
|
|
}
|
|
|
|
#[derive(Debug, Clone, serde::Serialize, utoipa::ToSchema)]
|
|
pub struct Paged<T> {
|
|
pub items: Vec<T>,
|
|
pub page: u32,
|
|
pub page_size: u32,
|
|
pub total: i64,
|
|
}
|
|
|
|
pub async fn list_columns(
|
|
pool: &PgPool,
|
|
tenant_id: Uuid,
|
|
q: ListColumnsQuery,
|
|
) -> Result<Paged<Column>, AppError> {
|
|
let page = q.page.max(1);
|
|
let page_size = q.page_size.clamp(1, 200);
|
|
let offset = ((page - 1) * page_size) as i64;
|
|
let limit = page_size as i64;
|
|
|
|
let like = q.search.map(|s| format!("%{}%", s));
|
|
|
|
let total: i64 = sqlx::query_scalar(
|
|
r#"
|
|
SELECT COUNT(*)
|
|
FROM cms_columns
|
|
WHERE tenant_id = $1
|
|
AND ($2::uuid IS NULL OR parent_id = $2)
|
|
AND ($3::text IS NULL OR name ILIKE $3 OR slug ILIKE $3)
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(q.parent_id)
|
|
.bind(like.as_deref())
|
|
.fetch_one(pool)
|
|
.await?;
|
|
|
|
let items = sqlx::query_as::<_, Column>(
|
|
r#"
|
|
SELECT tenant_id, id, name, slug, description, parent_id, sort_order, created_at, updated_at
|
|
FROM cms_columns
|
|
WHERE tenant_id = $1
|
|
AND ($2::uuid IS NULL OR parent_id = $2)
|
|
AND ($3::text IS NULL OR name ILIKE $3 OR slug ILIKE $3)
|
|
ORDER BY sort_order ASC, updated_at DESC
|
|
OFFSET $4
|
|
LIMIT $5
|
|
"#,
|
|
)
|
|
.bind(tenant_id)
|
|
.bind(q.parent_id)
|
|
.bind(like.as_deref())
|
|
.bind(offset)
|
|
.bind(limit)
|
|
.fetch_all(pool)
|
|
.await?;
|
|
|
|
Ok(Paged {
|
|
items,
|
|
page,
|
|
page_size,
|
|
total,
|
|
})
|
|
}
|