Record Message Event Response endpoint (#22)
textsender_api PR / Rustfmt (pull_request) Successful in 48s
textsender_api PR / Check (pull_request) Successful in 1m39s
textsender_api PR / Clippy (pull_request) Successful in 1m39s

Reviewed-on: phoenix/textsender_api#22
This commit was merged in pull request #22.
This commit is contained in:
2026-06-20 13:38:23 -04:00
parent e6f14917f0
commit a9d7429d75
8 changed files with 335 additions and 8 deletions
+98
View File
@@ -0,0 +1,98 @@
pub mod request {
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Deserialize, Serialize, ToSchema)]
pub struct RecordMessageEventRequest {
pub scheduled_message_event_id: uuid::Uuid,
pub response: serde_json::Value,
pub user_id: uuid::Uuid,
#[serde(with = "time::serde::rfc3339::option")]
pub sent: Option<time::OffsetDateTime>,
pub status: String,
pub contact_id: uuid::Uuid,
pub message_id: uuid::Uuid,
}
impl RecordMessageEventRequest {
pub fn is_valid(&self) -> bool {
!self.scheduled_message_event_id.is_nil()
|| !self.response.is_null()
|| !self.user_id.is_nil()
|| self.sent.is_some()
|| !self.status.is_empty()
|| !self.contact_id.is_nil()
|| !self.message_id.is_nil()
}
}
}
pub mod response {
use serde::{Deserialize, Serialize};
use utoipa::ToSchema;
#[derive(Debug, Default, Deserialize, Serialize, ToSchema)]
pub struct RecordMessageEventResponse {
pub message: String,
pub data: Vec<textsender_models::message::event::MessageEventResponse>,
}
}
pub mod endpoint {
use crate::repo::message::event as event_repo;
/// Endpoint to create a Message Event Response
#[utoipa::path(
post,
path = crate::caller::endpoints::RECORD_MESSAGE_EVENT_RESPONSE,
request_body(
content = super::request::RecordMessageEventRequest,
description = "Data needed to create a Message Event Response",
content_type = "application/json"
),
responses(
(status = 201, description = "Message Event Response created", body = super::response::RecordMessageEventResponse),
(status = 400, description = "Error", body = super::response::RecordMessageEventResponse),
(status = 500, description = "Error creating Message Event Response", body = super::response::RecordMessageEventResponse)
)
)]
pub async fn record_message_event_response(
axum::Extension(pool): axum::Extension<sqlx::PgPool>,
axum::Json(payload): axum::Json<super::request::RecordMessageEventRequest>,
) -> (
axum::http::StatusCode,
axum::Json<super::response::RecordMessageEventResponse>,
) {
let mut response = super::response::RecordMessageEventResponse::default();
if payload.is_valid() {
let mut mer = textsender_models::message::event::MessageEventResponse {
scheduled_message_event_id: payload.scheduled_message_event_id,
user_id: payload.user_id,
sent: payload.sent,
status: payload.status,
contact_id: payload.contact_id,
message_id: payload.message_id,
response: payload.response,
..Default::default()
};
match event_repo::insert(&pool, &mer).await {
Ok(id) => {
mer.id = id;
response.message = String::from(super::super::super::response::SUCCESSFUL);
response.data.push(mer);
(axum::http::StatusCode::CREATED, axum::Json(response))
}
Err(err) => {
eprintln!("Error: {err:?}");
response.message = String::from("Request body is not valid");
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
} else {
response.message = String::from("Request body is not valid");
(axum::http::StatusCode::BAD_REQUEST, axum::Json(response))
}
}
}
+1
View File
@@ -1,3 +1,4 @@
pub mod event;
pub mod scheduling;
pub mod request {
+3
View File
@@ -28,6 +28,9 @@ pub mod endpoints {
pub const DELETE_SCHEDULED_MESSAGE_EVENT: &str = "/api/v1/schedule/message/event/{id}";
/// Constant for fetching Scheduled Message endpoint
pub const FETCH_SCHEDULED_MESSAGE: &str = "/api/v1/schedule/message/fetch";
/// Constant for recording Message Event Response endpoint
pub const RECORD_MESSAGE_EVENT_RESPONSE: &str =
"/api/v1/schedule/message/event/response/record";
}
pub mod response {
+12 -1
View File
@@ -16,10 +16,13 @@ pub mod init {
use crate::caller::contact as contact_caller;
use crate::caller::message as message_caller;
use crate::caller::message::event as event_caller;
use crate::caller::message::scheduling as scheduling_caller;
use contact_caller::endpoint as contact_endpoints;
use contact_caller::response as contact_responses;
use event_caller::endpoint as event_endpoints;
use event_caller::response as event_responses;
use message_caller::endpoint as message_endpoints;
use message_caller::response as message_responses;
use scheduling_caller::endpoint as scheduling_endpoints;
@@ -85,7 +88,9 @@ pub mod init {
scheduling_endpoints::schedule_message,
),
components(schemas(contact_responses::AddContactResponse, message_responses::AddMessageResponse,
scheduling_responses::ScheduleMessageResponse)),
scheduling_responses::ScheduleMessageResponse,
event_responses::RecordMessageEventResponse
)),
tags(
(name = "textsender API", description = "Web API to manage texting")
)
@@ -166,6 +171,12 @@ pub mod init {
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.route(
crate::caller::endpoints::RECORD_MESSAGE_EVENT_RESPONSE,
post(event_endpoints::record_message_event_response).route_layer(
axum::middleware::from_fn(crate::auth::auth::<axum::body::Body>),
),
)
.layer(cors::configure_cors().await)
}
+2 -1
View File
@@ -89,8 +89,9 @@ pub async fn get_with_user_id(
async fn parse_row(
row: &sqlx::postgres::PgRow,
) -> Result<textsender_models::message::event::MessageEventResponse, sqlx::Error> {
println!("Parsing MER");
let id: uuid::Uuid = row.try_get("id")?;
let response: String = row.try_get("response")?;
let response: serde_json::Value = row.try_get("response")?;
let status: String = row.try_get("status")?;
let contact_id: uuid::Uuid = row.try_get("contact_id")?;
let message_id: uuid::Uuid = row.try_get("message_id")?;