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::{
create_label_use_case::CreateLabelUseCase,
get_all_labels_use_case::GetAllLabelsUseCase,
get_label_by_id_use_case::GetLabelByIdUseCase,
update_label_use_case::UpdateLabelUseCase,
},
},
@ -31,12 +32,15 @@ pub trait LabelController: Send + Sync {
) -> Result<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 {
create_label_use_case: Arc<dyn CreateLabelUseCase>,
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
get_label_by_id_use_case: Arc<dyn GetLabelByIdUseCase>,
}
impl LabelControllerImpl {
@ -44,11 +48,13 @@ impl LabelControllerImpl {
create_label_use_case: Arc<dyn CreateLabelUseCase>,
update_label_use_case: Arc<dyn UpdateLabelUseCase>,
get_all_labels_use_case: Arc<dyn GetAllLabelsUseCase>,
get_label_by_id_use_case: Arc<dyn GetLabelByIdUseCase>,
) -> Self {
Self {
create_label_use_case,
update_label_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> {
let result = self.get_all_labels_use_case.execute().await;
let result = self.get_all_labels_use_case.execute().await?;
result.map(|labels| {
labels
.into_iter()
.map(|label| LabelResponseDto::from(label))
.collect()
})
Ok(result
.into_iter()
.map(|label| LabelResponseDto::from(label))
.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 get_all_labels_use_case;
pub mod get_label_by_id_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 get_all_labels_handler;
pub mod get_label_by_id_handler;
pub mod label_api_doc;
pub mod label_web_routes;
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};
#[derive(OpenApi)]
#[openapi(paths(
create_label_handler::create_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;

View File

@ -2,13 +2,14 @@ use actix_web::web;
use crate::framework::web::{
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) {
cfg.service(
web::scope("/label")
.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("/{id}", web::put().to(update_label_handler)),
);

View File

@ -35,6 +35,7 @@ use label::{
application::use_case::{
create_label_use_case::CreateLabelUseCaseImpl,
get_all_labels_use_case::GetAllLabelsUseCaseImpl,
get_label_by_id_use_case::GetLabelByIdUseCaseImpl,
update_label_use_case::UpdateLabelUseCaseImpl,
},
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 get_all_labels_use_case =
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(
create_label_use_case,
update_label_use_case,
get_all_labels_use_case,
get_label_by_id_use_case,
));
// Post