GeneIT/geneit_backend/src/controllers/members_controller.rs

243 lines
7.2 KiB
Rust
Raw Normal View History

2023-08-04 17:03:46 +00:00
use crate::constants::{SizeConstraint, StaticConstraints};
use crate::controllers::HttpResult;
use crate::extractors::family_extractor::FamilyInPath;
use crate::models::{Member, MemberID, Sex};
use crate::services::members_service;
use crate::utils::countries_utils;
use actix_web::{web, HttpResponse};
serde_with::with_prefix!(prefix_birth "birth_");
serde_with::with_prefix!(prefix_death "death_");
#[derive(serde::Deserialize)]
pub struct RequestDate {
pub year: Option<i16>,
pub month: Option<i16>,
pub day: Option<i16>,
}
impl RequestDate {
pub fn check(&self) -> bool {
let c = StaticConstraints::default();
self.year.map(|y| c.date_year.validate(y)).unwrap_or(true)
&& self.month.map(|y| c.date_month.validate(y)).unwrap_or(true)
&& self.day.map(|y| c.date_day.validate(y)).unwrap_or(true)
}
}
#[derive(serde::Deserialize)]
pub struct MemberRequest {
first_name: Option<String>,
last_name: Option<String>,
birth_last_name: Option<String>,
email: Option<String>,
phone: Option<String>,
address: Option<String>,
city: Option<String>,
postal_code: Option<String>,
country: Option<String>,
sex: Option<Sex>,
mother: Option<MemberID>,
father: Option<MemberID>,
#[serde(flatten, with = "prefix_birth")]
birth: Option<RequestDate>,
#[serde(flatten, with = "prefix_death")]
death: Option<RequestDate>,
note: Option<String>,
}
#[derive(thiserror::Error, Debug)]
enum MemberControllerErr {
#[error("Malformed first name!")]
MalformedFirstname,
#[error("Malformed last name!")]
MalformedLastname,
#[error("Malformed birth last name!")]
MalformedBirthLastname,
#[error("Malformed email address!")]
MalformedEmailAddress,
#[error("Invalid email address!")]
InvalidEmailAddress,
#[error("Malformed phone number!")]
MalformedPhoneNumber,
#[error("Malformed address!")]
MalformedAddress,
#[error("Malformed city!")]
MalformedCity,
#[error("Malformed postal code!")]
MalformedPostalCode,
#[error("Malformed country!")]
MalformedCountry,
#[error("Invalid country code!")]
InvalidCountryCode,
#[error("Malformed date of birth!")]
MalformedDateOfBirth,
#[error("Malformed date of death!")]
MalformedDateOfDeath,
#[error("Malformed note!")]
MalformedNote,
#[error("Mother does not exists!")]
MotherNotExisting,
#[error("Father does not exists!")]
FatherNotExisting,
}
fn check_opt_str_val(
val: &Option<String>,
c: SizeConstraint,
err: MemberControllerErr,
) -> anyhow::Result<()> {
if let Some(v) = val {
if !c.validate(v) {
return Err(err.into());
}
}
Ok(())
}
impl MemberRequest {
pub async fn to_member(self, member: &mut Member) -> anyhow::Result<()> {
let c = StaticConstraints::default();
check_opt_str_val(
&self.first_name,
c.member_first_name,
MemberControllerErr::MalformedFirstname,
)?;
check_opt_str_val(
&self.last_name,
c.member_last_name,
MemberControllerErr::MalformedLastname,
)?;
check_opt_str_val(
&self.birth_last_name,
c.member_birth_last_name,
MemberControllerErr::MalformedBirthLastname,
)?;
check_opt_str_val(
&self.email,
c.member_email,
MemberControllerErr::MalformedEmailAddress,
)?;
if let Some(mail) = &self.email {
if !mailchecker::is_valid(mail) {
return Err(MemberControllerErr::InvalidEmailAddress.into());
}
}
check_opt_str_val(
&self.phone,
c.member_phone,
MemberControllerErr::MalformedPhoneNumber,
)?;
check_opt_str_val(
&self.address,
c.member_address,
MemberControllerErr::MalformedAddress,
)?;
check_opt_str_val(
&self.city,
c.member_city,
MemberControllerErr::MalformedCity,
)?;
check_opt_str_val(
&self.postal_code,
c.member_postal_code,
MemberControllerErr::MalformedPostalCode,
)?;
check_opt_str_val(
&self.country,
c.member_country,
MemberControllerErr::MalformedCountry,
)?;
if let Some(c) = &self.country {
if !countries_utils::is_code_valid(c) {
return Err(MemberControllerErr::InvalidCountryCode.into());
}
}
if let Some(d) = &self.birth {
if !d.check() {
return Err(MemberControllerErr::MalformedDateOfBirth.into());
}
}
if let Some(d) = &self.death {
if !d.check() {
return Err(MemberControllerErr::MalformedDateOfDeath.into());
}
}
check_opt_str_val(
&self.note,
c.member_note,
MemberControllerErr::MalformedNote,
)?;
if let Some(mother) = self.mother {
if !members_service::exists(member.family_id(), mother).await? {
return Err(MemberControllerErr::MotherNotExisting.into());
}
}
if let Some(father) = self.father {
if !members_service::exists(member.family_id(), father).await? {
return Err(MemberControllerErr::FatherNotExisting.into());
}
}
member.first_name = self.first_name;
member.last_name = self.last_name;
member.birth_last_name = self.birth_last_name;
member.email = self.email;
member.phone = self.phone;
member.address = self.address;
member.city = self.city;
member.postal_code = self.postal_code;
member.country = self.country;
member.set_sex(self.sex);
member.set_mother(self.mother);
member.set_father(self.father);
member.birth_year = self.birth.as_ref().map(|m| m.year).unwrap_or_default();
member.birth_month = self.birth.as_ref().map(|m| m.month).unwrap_or_default();
member.birth_day = self.birth.as_ref().map(|m| m.day).unwrap_or_default();
member.death_year = self.death.as_ref().map(|m| m.year).unwrap_or_default();
member.death_month = self.death.as_ref().map(|m| m.month).unwrap_or_default();
member.death_day = self.death.as_ref().map(|m| m.day).unwrap_or_default();
member.note = self.note;
Ok(())
}
}
/// Create a new family member
pub async fn create(f: FamilyInPath, req: web::Json<MemberRequest>) -> HttpResult {
let mut member = members_service::create(f.family_id()).await?;
if let Err(e) = req.0.to_member(&mut member).await {
log::error!("Failed to apply member information! {e}");
members_service::delete(&member).await?;
return Ok(HttpResponse::BadRequest().body(e.to_string()));
}
if let Err(e) = members_service::update(&mut member).await {
log::error!("Failed to update member information! {e}");
members_service::delete(&member).await?;
return Ok(HttpResponse::InternalServerError().finish());
}
Ok(HttpResponse::Ok().json(member))
}