use crate::controllers::members_controller::RequestDate; use crate::controllers::HttpResult; use crate::extractors::couple_extractor::FamilyAndCoupleInPath; use crate::extractors::family_extractor::FamilyInPath; use crate::models::{Couple, CoupleState, MemberID, PhotoID}; use crate::services::{couples_service, members_service, photos_service}; use actix_multipart::form::tempfile::TempFile; use actix_multipart::form::MultipartForm; use actix_web::{web, HttpResponse}; serde_with::with_prefix!(prefix_wedding "wedding_"); serde_with::with_prefix!(prefix_divorce "divorce_"); #[derive(thiserror::Error, Debug)] enum CoupleControllerErr { #[error("Wife and husband are identical!")] IdenticalWifeHusband, #[error("Wife does not exist!")] WifeNotExisting, #[error("Husband does not exist!")] HusbandNotExisting, #[error("Invalid date of wedding")] MalformedDateOfWedding, #[error("Invalid date of divorce")] MalformedDateOfDivorce, } #[derive(serde::Deserialize, Clone)] pub struct CoupleRequest { pub wife: Option, pub husband: Option, state: Option, #[serde(flatten, with = "prefix_wedding")] wedding: Option, #[serde(flatten, with = "prefix_divorce")] divorce: Option, } impl CoupleRequest { pub async fn to_couple(self, couple: &mut Couple) -> anyhow::Result<()> { if let Some(wife) = self.wife { if !members_service::exists(couple.family_id(), wife).await? { return Err(CoupleControllerErr::WifeNotExisting.into()); } if self.wife == self.husband { return Err(CoupleControllerErr::IdenticalWifeHusband.into()); } } if let Some(husband) = self.husband { if !members_service::exists(couple.family_id(), husband).await? { return Err(CoupleControllerErr::HusbandNotExisting.into()); } } if let Some(d) = &self.wedding { if !d.check() { return Err(CoupleControllerErr::MalformedDateOfWedding.into()); } } if let Some(d) = &self.divorce { if !d.check() { return Err(CoupleControllerErr::MalformedDateOfDivorce.into()); } } couple.set_wife(self.wife); couple.set_husband(self.husband); couple.set_state(self.state); couple.wedding_year = self.wedding.as_ref().map(|m| m.year).unwrap_or_default(); couple.wedding_month = self.wedding.as_ref().map(|m| m.month).unwrap_or_default(); couple.wedding_day = self.wedding.as_ref().map(|m| m.day).unwrap_or_default(); couple.divorce_year = self.divorce.as_ref().map(|m| m.year).unwrap_or_default(); couple.divorce_month = self.divorce.as_ref().map(|m| m.month).unwrap_or_default(); couple.divorce_day = self.divorce.as_ref().map(|m| m.day).unwrap_or_default(); Ok(()) } } #[derive(serde::Serialize)] struct CoupleAPI { #[serde(flatten)] member: Couple, signed_photo_id: Option, } impl CoupleAPI { pub fn new(member: Couple) -> Self { Self { signed_photo_id: member.photo_id().as_ref().map(PhotoID::to_signed_hash), member, } } } /// Create a new couple pub async fn create(m: FamilyInPath, req: web::Json) -> HttpResult { let mut couple = couples_service::create(m.family_id()).await?; if let Err(e) = req.0.to_couple(&mut couple).await { log::error!("Failed to apply couple information! {e}"); couples_service::delete(&mut couple).await?; return Ok(HttpResponse::BadRequest().body(e.to_string())); } if let Err(e) = couples_service::update(&mut couple).await { log::error!("Failed to update couple information! {e}"); couples_service::delete(&mut couple).await?; return Ok(HttpResponse::InternalServerError().finish()); } Ok(HttpResponse::Ok().json(couple)) } /// Get the entire list of couples pub async fn get_all(m: FamilyInPath) -> HttpResult { let couples = couples_service::get_all_of_family(m.family_id()) .await? .into_iter() .map(CoupleAPI::new) .collect::>(); Ok(HttpResponse::Ok().json(couples)) } /// Get a single couple entry pub async fn get_single(m: FamilyAndCoupleInPath) -> HttpResult { Ok(HttpResponse::Ok().json(CoupleAPI::new(m.to_couple()))) } /// Update a couple information pub async fn update(m: FamilyAndCoupleInPath, req: web::Json) -> HttpResult { let mut couple = m.to_couple(); if let Err(e) = req.0.to_couple(&mut couple).await { log::error!("Failed to parse couple information {e}!"); return Ok(HttpResponse::BadRequest().body(e.to_string())); } couples_service::update(&mut couple).await?; Ok(HttpResponse::Accepted().finish()) } /// Delete a couple pub async fn delete(m: FamilyAndCoupleInPath) -> HttpResult { couples_service::delete(&mut m.to_couple()).await?; Ok(HttpResponse::Ok().finish()) } #[derive(Debug, MultipartForm)] pub struct UploadPhotoForm { #[multipart(rename = "photo")] photo: TempFile, } /// Upload a new photo for a user pub async fn set_photo( m: FamilyAndCoupleInPath, MultipartForm(form): MultipartForm, ) -> HttpResult { let photo = photos_service::finalize_upload(form.photo.into()).await?; let mut couple = m.to_couple(); couples_service::remove_photo(&mut couple).await?; couple.set_photo_id(Some(photo.id())); couples_service::update(&mut couple).await?; Ok(HttpResponse::Ok().finish()) } /// Remove a photo pub async fn remove_photo(m: FamilyAndCoupleInPath) -> HttpResult { let mut couple = m.to_couple(); couples_service::remove_photo(&mut couple).await?; Ok(HttpResponse::Ok().finish()) }