Files
imphnen-backend-service/imphnen-hackathon/src/v1/hackathon/hackathon_service.rs
T
MythEclipse e530eba60d Add comprehensive tests for hackathon service functionality
- Implemented tests for creating, retrieving, updating, and deleting hackathons.
- Added validation tests for hackathon creation and updates.
- Included tests for hackathon events and timelines, ensuring proper handling of edge cases.
- Created tests for hackathon submissions, including validation and submission status updates.
- Organized tests into a dedicated module for better structure and maintainability.
2025-09-27 13:01:08 +07:00

829 lines
33 KiB
Rust

use std::pin::Pin;
use std::future::Future;
use super::hackathon_dto::{
HackathonCreateRequestDto, HackathonDto, HackathonEventCreateRequestDto, HackathonEventDto,
HackathonEventUpdateRequestDto, HackathonSubmissionCreateRequestDto,
HackathonSubmissionDto, HackathonSubmissionUpdateRequestDto, HackathonTimelineCreateRequestDto,
HackathonTimelineDto, HackathonTimelineUpdateRequestDto, HackathonUpdateRequestDto,
};
use super::hackathon_repository::HackathonRepository;
use crate::{AppState, ResponseSuccessDto, ErrorDto};
use imphnen_utils::{validator::validate_request};
use imphnen_libs::{MetaRequestDto, ResponseListSuccessDto};
use axum::http::StatusCode;
use tracing::error;
pub trait HackathonServiceTrait: Send + Sync + 'static {
// Hackathon operations
fn create_hackathon(
payload: HackathonCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>>;
fn get_hackathon(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>>;
fn list_hackathons(
meta: MetaRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonDto>>, ErrorDto>> + Send>>;
fn update_hackathon(
id: String,
payload: HackathonUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>>;
fn delete_hackathon(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>>;
// Hackathon Events operations
fn create_hackathon_event(
hackathon_id: String,
payload: HackathonEventCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>>;
fn list_hackathon_events(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonEventDto>>, ErrorDto>> + Send>>;
fn update_hackathon_event(
id: String,
payload: HackathonEventUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>>;
fn delete_hackathon_event(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>>;
// Hackathon Timeline operations
fn create_hackathon_timeline(
hackathon_id: String,
payload: HackathonTimelineCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>>;
fn list_hackathon_timeline(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonTimelineDto>>, ErrorDto>> + Send>>;
fn update_hackathon_timeline(
id: String,
payload: HackathonTimelineUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>>;
fn delete_hackathon_timeline(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>>;
// Hackathon Submissions operations
fn create_hackathon_submission(
hackathon_id: String,
team_id: String,
payload: HackathonSubmissionCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>>;
fn list_hackathon_submissions(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonSubmissionDto>>, ErrorDto>> + Send>>;
fn update_hackathon_submission(
id: String,
payload: HackathonSubmissionUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>>;
fn submit_hackathon_submission(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>>;
fn delete_hackathon_submission(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>>;
}
#[derive(Clone)]
pub struct HackathonService;
impl HackathonServiceTrait for HackathonService {
fn create_hackathon(
payload: HackathonCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err((_, error_message)) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": error_message })),
});
}
// Business logic validation
if payload.end_date <= payload.start_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "End date must be after start date".to_string(),
details: None,
});
}
if payload.registration_deadline >= payload.start_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Registration deadline must be before start date".to_string(),
details: None,
});
}
if payload.organizers.is_empty() {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "At least one organizer is required".to_string(),
details: None,
});
}
let repo = HackathonRepository::new(&state);
match repo.create_hackathon(payload).await {
Ok(hackathon) => {
let dto = HackathonDto::from(hackathon);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to create hackathon: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to create hackathon".to_string(),
details: None,
})
}
}
})
}
fn get_hackathon(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.get_hackathon_by_id(id).await {
Ok(hackathon) => {
let dto = HackathonDto::from(hackathon);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to get hackathon: {}", e);
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
})
}
}
})
}
fn list_hackathons(
meta: MetaRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonDto>>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.list_hackathons(meta).await {
Ok(result) => {
let dtos: Vec<HackathonDto> = result.data.into_iter().map(HackathonDto::from).collect();
Ok(ResponseListSuccessDto {
data: dtos,
meta: result.meta,
})
}
Err(e) => {
error!("Failed to list hackathons: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to list hackathons".to_string(),
details: None,
})
}
}
})
}
fn update_hackathon(
id: String,
payload: HackathonUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err(errors) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": errors.1 })),
});
}
let repo = HackathonRepository::new(&state);
// Get existing hackathon for validation
let existing = match repo.get_hackathon_by_id(id.clone()).await {
Ok(h) => h,
Err(_) => {
return Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
});
}
};
// Business logic validation
let start_date = payload.start_date.unwrap_or(existing.start_date);
let end_date = payload.end_date.unwrap_or(existing.end_date);
let registration_deadline = payload.registration_deadline.unwrap_or(existing.registration_deadline);
if end_date <= start_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "End date must be after start date".to_string(),
details: None,
});
}
if registration_deadline >= start_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Registration deadline must be before start date".to_string(),
details: None,
});
}
match repo.update_hackathon(id, payload).await {
Ok(hackathon) => {
let dto = HackathonDto::from(hackathon);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to update hackathon: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to update hackathon".to_string(),
details: None,
})
}
}
})
}
fn delete_hackathon(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.delete_hackathon(id).await {
Ok(message) => Ok(ResponseSuccessDto { data: message }),
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("Failed to delete") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
})
} else {
error!("Failed to delete hackathon: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to delete hackathon".to_string(),
details: None,
})
}
}
}
})
}
fn create_hackathon_event(
hackathon_id: String,
payload: HackathonEventCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err((_, error_message)) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": error_message })),
});
}
// Business logic validation
if payload.end_time <= payload.start_time {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "End time must be after start time".to_string(),
details: None,
});
}
let repo = HackathonRepository::new(&state);
// Verify hackathon exists
if repo.get_hackathon_by_id(hackathon_id.clone()).await.is_err() {
return Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
});
}
match repo.create_hackathon_event(hackathon_id, payload).await {
Ok(event) => {
let dto = HackathonEventDto::from(event);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to create hackathon event: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to create hackathon event".to_string(),
details: None,
})
}
}
})
}
fn list_hackathon_events(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonEventDto>>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.list_hackathon_events(meta, hackathon_id).await {
Ok(result) => {
let dtos: Vec<HackathonEventDto> = result.data.into_iter().map(HackathonEventDto::from).collect();
Ok(ResponseListSuccessDto {
data: dtos,
meta: result.meta,
})
}
Err(e) => {
error!("Failed to list hackathon events: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to list hackathon events".to_string(),
details: None,
})
}
}
})
}
fn update_hackathon_event(
id: String,
payload: HackathonEventUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonEventDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err((_, error_message)) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": error_message })),
});
}
let repo = HackathonRepository::new(&state);
match repo.update_hackathon_event(id, payload).await {
Ok(event) => {
let dto = HackathonEventDto::from(event);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("not found") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Event not found".to_string(),
details: None,
})
} else {
error!("Failed to update hackathon event: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to update hackathon event".to_string(),
details: None,
})
}
}
}
})
}
fn delete_hackathon_event(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.delete_hackathon_event(id).await {
Ok(message) => Ok(ResponseSuccessDto { data: message }),
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("Failed to delete") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Event not found".to_string(),
details: None,
})
} else {
error!("Failed to delete hackathon event: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to delete hackathon event".to_string(),
details: None,
})
}
}
}
})
}
fn create_hackathon_timeline(
hackathon_id: String,
payload: HackathonTimelineCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err(errors) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": errors.1 })),
});
}
// Business logic validation
if payload.end_date <= payload.start_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "End date must be after start date".to_string(),
details: None,
});
}
let repo = HackathonRepository::new(&state);
// Verify hackathon exists
if repo.get_hackathon_by_id(hackathon_id.clone()).await.is_err() {
return Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
});
}
match repo.create_hackathon_timeline(hackathon_id, payload).await {
Ok(timeline) => {
let dto = HackathonTimelineDto::from(timeline);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to create hackathon timeline: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to create hackathon timeline".to_string(),
details: None,
})
}
}
})
}
fn list_hackathon_timeline(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonTimelineDto>>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.list_hackathon_timeline(meta, hackathon_id).await {
Ok(result) => {
let dtos: Vec<HackathonTimelineDto> = result.data.into_iter().map(HackathonTimelineDto::from).collect();
Ok(ResponseListSuccessDto {
data: dtos,
meta: result.meta,
})
}
Err(e) => {
error!("Failed to list hackathon timeline: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to list hackathon timeline".to_string(),
details: None,
})
}
}
})
}
fn update_hackathon_timeline(
id: String,
payload: HackathonTimelineUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonTimelineDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err(errors) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": errors.1 })),
});
}
let repo = HackathonRepository::new(&state);
match repo.update_hackathon_timeline(id, payload).await {
Ok(timeline) => {
let dto = HackathonTimelineDto::from(timeline);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("not found") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Timeline not found".to_string(),
details: None,
})
} else {
error!("Failed to update hackathon timeline: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to update hackathon timeline".to_string(),
details: None,
})
}
}
}
})
}
fn delete_hackathon_timeline(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.delete_hackathon_timeline(id).await {
Ok(message) => Ok(ResponseSuccessDto { data: message }),
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("Failed to delete") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Timeline not found".to_string(),
details: None,
})
} else {
error!("Failed to delete hackathon timeline: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to delete hackathon timeline".to_string(),
details: None,
})
}
}
}
})
}
fn create_hackathon_submission(
hackathon_id: String,
team_id: String,
payload: HackathonSubmissionCreateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err(errors) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": errors.1 })),
});
}
let repo = HackathonRepository::new(&state);
// Verify hackathon exists
if repo.get_hackathon_by_id(hackathon_id.clone()).await.is_err() {
return Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Hackathon not found".to_string(),
details: None,
});
}
match repo.create_hackathon_submission(hackathon_id, team_id, payload).await {
Ok(submission) => {
let dto = HackathonSubmissionDto::from(submission);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
error!("Failed to create hackathon submission: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to create hackathon submission".to_string(),
details: None,
})
}
}
})
}
fn list_hackathon_submissions(
meta: MetaRequestDto,
hackathon_id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseListSuccessDto<Vec<HackathonSubmissionDto>>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.list_hackathon_submissions(meta, hackathon_id).await {
Ok(result) => {
let dtos: Vec<HackathonSubmissionDto> = result.data.into_iter().map(HackathonSubmissionDto::from).collect();
Ok(ResponseListSuccessDto {
data: dtos,
meta: result.meta,
})
}
Err(e) => {
error!("Failed to list hackathon submissions: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to list hackathon submissions".to_string(),
details: None,
})
}
}
})
}
fn update_hackathon_submission(
id: String,
payload: HackathonSubmissionUpdateRequestDto,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>> {
let payload = payload;
let state = state.to_owned();
Box::pin(async move {
// Validate request
if let Err(errors) = validate_request(&payload) {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Validation failed".to_string(),
details: Some(serde_json::json!({ "validation_errors": errors.1 })),
});
}
let repo = HackathonRepository::new(&state);
match repo.update_hackathon_submission(id, payload).await {
Ok(submission) => {
let dto = HackathonSubmissionDto::from(submission);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("not found") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Submission not found".to_string(),
details: None,
})
} else {
error!("Failed to update hackathon submission: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to update hackathon submission".to_string(),
details: None,
})
}
}
}
})
}
fn submit_hackathon_submission(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<HackathonSubmissionDto>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.submit_hackathon_submission(id).await {
Ok(submission) => {
let dto = HackathonSubmissionDto::from(submission);
Ok(ResponseSuccessDto { data: dto })
}
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("not found") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Submission not found".to_string(),
details: None,
})
} else {
error!("Failed to submit hackathon submission: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to submit hackathon submission".to_string(),
details: None,
})
}
}
}
})
}
fn delete_hackathon_submission(
id: String,
state: &AppState,
) -> Pin<Box<dyn Future<Output = Result<ResponseSuccessDto<String>, ErrorDto>> + Send>> {
let state = state.to_owned();
Box::pin(async move {
let repo = HackathonRepository::new(&state);
match repo.delete_hackathon_submission(id).await {
Ok(message) => Ok(ResponseSuccessDto { data: message }),
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("Failed to delete") {
Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Submission not found".to_string(),
details: None,
})
} else {
error!("Failed to delete hackathon submission: {}", e);
Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to delete hackathon submission".to_string(),
details: None,
})
}
}
}
})
}
}