gitdataai/libs/room/src/category.rs
2026-04-15 09:08:09 +08:00

169 lines
5.4 KiB
Rust

use crate::error::RoomError;
use crate::service::RoomService;
use crate::ws_context::WsUserContext;
use chrono::Utc;
use models::rooms::{room, room_category};
use queue::ProjectRoomEvent;
use sea_orm::prelude::Expr;
use sea_orm::*;
use uuid::Uuid;
impl RoomService {
pub async fn room_category_list(
&self,
project_name: String,
ctx: &WsUserContext,
) -> Result<Vec<super::RoomCategoryResponse>, RoomError> {
let user_id = ctx.user_id;
let project = self.utils_find_project_by_name(project_name).await?;
self.check_project_access(project.id, user_id).await?;
let models = room_category::Entity::find()
.filter(room_category::Column::Project.eq(project.id))
.order_by_asc(room_category::Column::Position)
.all(&self.db)
.await?;
Ok(models
.into_iter()
.map(super::RoomCategoryResponse::from)
.collect())
}
pub async fn room_category_create(
&self,
project_name: String,
request: super::RoomCategoryCreateRequest,
ctx: &WsUserContext,
) -> Result<super::RoomCategoryResponse, RoomError> {
let user_id = ctx.user_id;
let project = self.utils_find_project_by_name(project_name).await?;
self.require_project_admin(project.id, user_id).await?;
Self::validate_name(&request.name, super::MAX_CATEGORY_NAME_LEN)?;
let position = if let Some(position) = request.position {
position
} else {
let max_position: Option<Option<i32>> = room_category::Entity::find()
.filter(room_category::Column::Project.eq(project.id))
.select_only()
.column_as(room_category::Column::Position.max(), "max_position")
.into_tuple::<Option<i32>>()
.one(&self.db)
.await?;
max_position.flatten().unwrap_or(0) + 1
};
let model = room_category::ActiveModel {
id: Set(Uuid::now_v7()),
project: Set(project.id),
name: Set(request.name),
position: Set(position),
created_by: Set(user_id),
created_at: Set(Utc::now()),
}
.insert(&self.db)
.await?;
let event = ProjectRoomEvent {
event_type: super::RoomEventType::CategoryCreated.as_str().into(),
project_id: project.id,
room_id: None,
category_id: Some(model.id),
message_id: None,
seq: None,
timestamp: Utc::now(),
};
let _ = self
.queue
.publish_project_room_event(project.id, event)
.await;
Ok(super::RoomCategoryResponse::from(model))
}
pub async fn room_category_update(
&self,
category_id: Uuid,
request: super::RoomCategoryUpdateRequest,
ctx: &WsUserContext,
) -> Result<super::RoomCategoryResponse, RoomError> {
let user_id = ctx.user_id;
let model = room_category::Entity::find_by_id(category_id)
.one(&self.db)
.await?
.ok_or_else(|| RoomError::NotFound("Room category not found".to_string()))?;
self.require_project_admin(model.project, user_id).await?;
let mut active: room_category::ActiveModel = model.into();
if let Some(name) = request.name {
active.name = Set(name);
}
if let Some(position) = request.position {
active.position = Set(position);
}
let updated = active.update(&self.db).await?;
let event = ProjectRoomEvent {
event_type: super::RoomEventType::CategoryUpdated.as_str().into(),
project_id: updated.project,
room_id: None,
category_id: Some(updated.id),
message_id: None,
seq: None,
timestamp: Utc::now(),
};
let _ = self
.queue
.publish_project_room_event(updated.project, event)
.await;
Ok(super::RoomCategoryResponse::from(updated))
}
pub async fn room_category_delete(
&self,
category_id: Uuid,
ctx: &WsUserContext,
) -> Result<(), RoomError> {
let user_id = ctx.user_id;
let model = room_category::Entity::find_by_id(category_id)
.one(&self.db)
.await?
.ok_or_else(|| RoomError::NotFound("Room category not found".to_string()))?;
self.require_project_admin(model.project, user_id).await?;
let project_id = model.project;
let txn = self.db.begin().await?;
room::Entity::update_many()
.col_expr(room::Column::Category, Expr::value(None::<Uuid>))
.filter(room::Column::Category.eq(category_id))
.exec(&txn)
.await?;
room_category::Entity::delete_by_id(category_id)
.exec(&txn)
.await?;
txn.commit().await?;
let event = ProjectRoomEvent {
event_type: super::RoomEventType::CategoryDeleted.as_str().into(),
project_id,
room_id: None,
category_id: Some(category_id),
message_id: None,
seq: None,
timestamp: Utc::now(),
};
let _ = self
.queue
.publish_project_room_event(project_id, event)
.await;
Ok(())
}
}