feat: Implement submission retrieval and timeline validation in hackathon service

This commit is contained in:
MythEclipse
2025-09-27 13:06:55 +07:00
parent e530eba60d
commit b0cf9817d7
2 changed files with 86 additions and 0 deletions
@@ -548,6 +548,28 @@ impl<'a> HackathonRepository<'a> {
}
}
#[instrument(skip(self, id), err)]
pub async fn get_hackathon_submission_by_id(&self, id: String) -> Result<HackathonSubmissionsSchema> {
let table = ResourceEnum::HackathonSubmissions.to_string();
info!(query = %format!("SELECT * FROM {} WHERE id = '{}'", table, id), "Executing SurrealDB query");
let record: Option<HackathonSubmissionsSchema> = self
.state
.surrealdb_ws
.select((table, id))
.await?;
match record {
Some(s) => {
if s.is_deleted {
bail!("Submission not found");
}
Ok(s)
}
None => bail!("Submission not found"),
}
}
#[instrument(skip(self, id), err)]
pub async fn submit_hackathon_submission(&self, id: String) -> Result<HackathonSubmissionsSchema> {
let table = ResourceEnum::HackathonSubmissions.to_string();
@@ -597,4 +619,17 @@ impl<'a> HackathonRepository<'a> {
None => bail!("Failed to delete submission"),
}
}
#[instrument(skip(self, hackathon_id), err)]
pub async fn get_submission_timeline_phase(&self, hackathon_id: String) -> Result<Option<HackathonTimelineSchema>> {
let table = ResourceEnum::HackathonTimeline.to_string();
info!(query = %format!("SELECT * FROM {} WHERE hackathon_id = 'app_hackathons:{}' AND phase = 'Submission' AND is_deleted = false LIMIT 1", table, hackathon_id), "Executing SurrealDB query");
let mut response = self.state.surrealdb_ws
.query(format!("SELECT * FROM {} WHERE hackathon_id = 'app_hackathons:{}' AND phase = 'Submission' AND is_deleted = false LIMIT 1", table, hackathon_id))
.await?;
let timeline: Option<HackathonTimelineSchema> = response.take(0)?;
Ok(timeline)
}
}
@@ -770,6 +770,57 @@ impl HackathonServiceTrait for HackathonService {
Box::pin(async move {
let repo = HackathonRepository::new(&state);
// Get submission to extract hackathon_id for timeline validation
let submission = match repo.get_hackathon_submission_by_id(id.clone()).await {
Ok(sub) => sub,
Err(e) => {
let error_msg = e.to_string();
if error_msg.contains("not found") {
return Err(ErrorDto {
status: StatusCode::NOT_FOUND.as_u16(),
message: "Submission not found".to_string(),
details: None,
});
} else {
error!("Failed to get submission for validation: {}", e);
return Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to validate submission".to_string(),
details: None,
});
}
}
};
// Check submission timeline phase
match repo.get_submission_timeline_phase(submission.hackathon_id.id.to_raw()).await {
Ok(Some(timeline_phase)) => {
let current_time = chrono::Utc::now();
if current_time < timeline_phase.start_date || current_time > timeline_phase.end_date {
return Err(ErrorDto {
status: StatusCode::BAD_REQUEST.as_u16(),
message: "Submission is not allowed outside the designated submission period".to_string(),
details: Some(serde_json::json!({
"start_date": timeline_phase.start_date,
"end_date": timeline_phase.end_date,
"current_time": current_time
})),
});
}
}
Ok(None) => {
// If no timeline phase defined, allow submission (backward compatibility)
}
Err(e) => {
error!("Failed to get submission timeline phase: {}", e);
return Err(ErrorDto {
status: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
message: "Failed to validate submission period".to_string(),
details: None,
});
}
}
match repo.submit_hackathon_submission(id).await {
Ok(submission) => {
let dto = HackathonSubmissionDto::from(submission);