169 lines
5.4 KiB
Rust
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(())
|
|
}
|
|
}
|