feat: backend implement get label by ID functionality in label management

This commit is contained in:
SquidSpirit 2025-10-15 15:01:40 +08:00
parent d1f085b255
commit d20a210857
8 changed files with 101 additions and 10 deletions

View File

@ -12,6 +12,7 @@ use crate::{
use_case::{ use_case::{
create_label_use_case::CreateLabelUseCase, create_label_use_case::CreateLabelUseCase,
get_all_labels_use_case::GetAllLabelsUseCase, get_all_labels_use_case::GetAllLabelsUseCase,
get_label_by_id_use_case::GetLabelByIdUseCase,
update_label_use_case::UpdateLabelUseCase, update_label_use_case::UpdateLabelUseCase,
}, },
}, },
@ -31,12 +32,15 @@ pub trait LabelController: Send + Sync {
) -> Result<LabelResponseDto, LabelError>; ) -> Result<LabelResponseDto, LabelError>;
async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, LabelError>; async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, LabelError>;
async fn get_label_by_id(&self, id: i32) -> Result<LabelResponseDto, LabelError>;
} }
pub struct LabelControllerImpl { pub struct LabelControllerImpl {
create_label_use_case: Arc<dyn CreateLabelUseCase>, create_label_use_case: Arc<dyn CreateLabelUseCase>,
update_label_use_case: Arc<dyn UpdateLabelUseCase>, update_label_use_case: Arc<dyn UpdateLabelUseCase>,
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>, get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
get_label_by_id_use_case: Arc<dyn GetLabelByIdUseCase>,
} }
impl LabelControllerImpl { impl LabelControllerImpl {
@ -44,11 +48,13 @@ impl LabelControllerImpl {
create_label_use_case: Arc<dyn CreateLabelUseCase>, create_label_use_case: Arc<dyn CreateLabelUseCase>,
update_label_use_case: Arc<dyn UpdateLabelUseCase>, update_label_use_case: Arc<dyn UpdateLabelUseCase>,
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>, get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
get_label_by_id_use_case: Arc<dyn GetLabelByIdUseCase>,
) -> Self { ) -> Self {
Self { Self {
create_label_use_case, create_label_use_case,
update_label_use_case, update_label_use_case,
get_all_labels_use_case, get_all_labels_use_case,
get_label_by_id_use_case,
} }
} }
} }
@ -83,13 +89,17 @@ impl LabelController for LabelControllerImpl {
} }
async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, LabelError> { async fn get_all_labels(&self) -> Result<Vec<LabelResponseDto>, LabelError> {
let result = self.get_all_labels_use_case.execute().await; let result = self.get_all_labels_use_case.execute().await?;
result.map(|labels| { Ok(result
labels .into_iter()
.into_iter() .map(|label| LabelResponseDto::from(label))
.map(|label| LabelResponseDto::from(label)) .collect())
.collect() }
})
async fn get_label_by_id(&self, id: i32) -> Result<LabelResponseDto, LabelError> {
let label = self.get_label_by_id_use_case.execute(id).await?;
Ok(LabelResponseDto::from(label))
} }
} }

View File

@ -1,3 +1,4 @@
pub mod create_label_use_case; pub mod create_label_use_case;
pub mod get_all_labels_use_case; pub mod get_all_labels_use_case;
pub mod get_label_by_id_use_case;
pub mod update_label_use_case; pub mod update_label_use_case;

View File

@ -0,0 +1,30 @@
use std::sync::Arc;
use async_trait::async_trait;
use crate::{
application::{error::label_error::LabelError, gateway::label_repository::LabelRepository},
domain::entity::label::Label,
};
#[async_trait]
pub trait GetLabelByIdUseCase: Send + Sync {
async fn execute(&self, id: i32) -> Result<Label, LabelError>;
}
pub struct GetLabelByIdUseCaseImpl {
repository: Arc<dyn LabelRepository>,
}
impl GetLabelByIdUseCaseImpl {
pub fn new(repository: Arc<dyn LabelRepository>) -> Self {
Self { repository }
}
}
#[async_trait]
impl GetLabelByIdUseCase for GetLabelByIdUseCaseImpl {
async fn execute(&self, id: i32) -> Result<Label, LabelError> {
self.repository.get_label_by_id(id).await
}
}

View File

@ -1,5 +1,6 @@
pub mod create_label_handler; pub mod create_label_handler;
pub mod get_all_labels_handler; pub mod get_all_labels_handler;
pub mod get_label_by_id_handler;
pub mod label_api_doc; pub mod label_api_doc;
pub mod label_web_routes; pub mod label_web_routes;
pub mod update_label_handler; pub mod update_label_handler;

View File

@ -0,0 +1,41 @@
use actix_web::{HttpResponse, Responder, web};
use anyhow::anyhow;
use sentry::integrations::anyhow::capture_anyhow;
use crate::{
adapter::delivery::{label_controller::LabelController, label_response_dto::LabelResponseDto},
application::error::label_error::LabelError,
};
#[utoipa::path(
get,
path = "/label/{id}",
tag = "label",
summary = "Get the label by ID",
responses(
(status = 200, body = LabelResponseDto),
(status = 404, description = LabelError::NotFound),
)
)]
pub async fn get_label_by_id_handler(
label_controller: web::Data<dyn LabelController>,
path: web::Path<i32>,
) -> impl Responder {
let id = path.into_inner();
let result = label_controller.get_label_by_id(id).await;
match result {
Ok(labels) => HttpResponse::Ok().json(labels),
Err(e) => match e {
LabelError::NotFound => HttpResponse::NotFound().finish(),
LabelError::Unauthorized | LabelError::DuplicatedLabelName => {
capture_anyhow(&anyhow!(e));
HttpResponse::InternalServerError().finish()
}
LabelError::Unexpected(e) => {
capture_anyhow(&e);
HttpResponse::InternalServerError().finish()
}
},
}
}

View File

@ -1,11 +1,14 @@
use crate::framework::web::{create_label_handler, get_all_labels_handler, update_label_handler}; use crate::framework::web::{
create_label_handler, get_all_labels_handler, get_label_by_id_handler, update_label_handler,
};
use utoipa::{OpenApi, openapi}; use utoipa::{OpenApi, openapi};
#[derive(OpenApi)] #[derive(OpenApi)]
#[openapi(paths( #[openapi(paths(
create_label_handler::create_label_handler, create_label_handler::create_label_handler,
update_label_handler::update_label_handler, update_label_handler::update_label_handler,
get_all_labels_handler::get_all_labels_handler get_all_labels_handler::get_all_labels_handler,
get_label_by_id_handler::get_label_by_id_handler
))] ))]
struct ApiDoc; struct ApiDoc;

View File

@ -2,13 +2,14 @@ use actix_web::web;
use crate::framework::web::{ use crate::framework::web::{
create_label_handler::create_label_handler, get_all_labels_handler::get_all_labels_handler, create_label_handler::create_label_handler, get_all_labels_handler::get_all_labels_handler,
update_label_handler::update_label_handler, get_label_by_id_handler::get_label_by_id_handler, update_label_handler::update_label_handler,
}; };
pub fn configure_label_routes(cfg: &mut web::ServiceConfig) { pub fn configure_label_routes(cfg: &mut web::ServiceConfig) {
cfg.service( cfg.service(
web::scope("/label") web::scope("/label")
.route("", web::get().to(get_all_labels_handler)) .route("", web::get().to(get_all_labels_handler))
.route("/{id}", web::get().to(get_label_by_id_handler))
.route("", web::post().to(create_label_handler)) .route("", web::post().to(create_label_handler))
.route("/{id}", web::put().to(update_label_handler)), .route("/{id}", web::put().to(update_label_handler)),
); );

View File

@ -35,6 +35,7 @@ use label::{
application::use_case::{ application::use_case::{
create_label_use_case::CreateLabelUseCaseImpl, create_label_use_case::CreateLabelUseCaseImpl,
get_all_labels_use_case::GetAllLabelsUseCaseImpl, get_all_labels_use_case::GetAllLabelsUseCaseImpl,
get_label_by_id_use_case::GetLabelByIdUseCaseImpl,
update_label_use_case::UpdateLabelUseCaseImpl, update_label_use_case::UpdateLabelUseCaseImpl,
}, },
framework::db::label_db_service_impl::LabelDbServiceImpl, framework::db::label_db_service_impl::LabelDbServiceImpl,
@ -104,11 +105,14 @@ impl Container {
let update_label_use_case = Arc::new(UpdateLabelUseCaseImpl::new(label_repository.clone())); let update_label_use_case = Arc::new(UpdateLabelUseCaseImpl::new(label_repository.clone()));
let get_all_labels_use_case = let get_all_labels_use_case =
Arc::new(GetAllLabelsUseCaseImpl::new(label_repository.clone())); Arc::new(GetAllLabelsUseCaseImpl::new(label_repository.clone()));
let get_label_by_id_use_case =
Arc::new(GetLabelByIdUseCaseImpl::new(label_repository.clone()));
let label_controller = Arc::new(LabelControllerImpl::new( let label_controller = Arc::new(LabelControllerImpl::new(
create_label_use_case, create_label_use_case,
update_label_use_case, update_label_use_case,
get_all_labels_use_case, get_all_labels_use_case,
get_label_by_id_use_case,
)); ));
// Post // Post