Can create couple
This commit is contained in:
		@@ -68,17 +68,20 @@ CREATE TABLE members (
 | 
				
			|||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
CREATE TABLE couples (
 | 
					CREATE TABLE couples (
 | 
				
			||||||
    wife integer NOT NULL REFERENCES members,
 | 
					    id SERIAL PRIMARY KEY,
 | 
				
			||||||
    husband integer NOT NULL REFERENCES members,
 | 
					    family_id integer NOT NULL REFERENCES families,
 | 
				
			||||||
 | 
					    wife integer NULL REFERENCES members,
 | 
				
			||||||
 | 
					    husband integer NULL REFERENCES members,
 | 
				
			||||||
 | 
					    state varchar(1) NULL,
 | 
				
			||||||
    photo_id INTEGER NULL REFERENCES photos ON DELETE SET NULL,
 | 
					    photo_id INTEGER NULL REFERENCES photos ON DELETE SET NULL,
 | 
				
			||||||
 | 
					    time_create BIGINT NOT NULL,
 | 
				
			||||||
 | 
					    time_update BIGINT NOT NULL,
 | 
				
			||||||
    wedding_year smallint NULL,
 | 
					    wedding_year smallint NULL,
 | 
				
			||||||
    wedding_month smallint NULL,
 | 
					    wedding_month smallint NULL,
 | 
				
			||||||
    wedding_day smallint NULL,
 | 
					    wedding_day smallint NULL,
 | 
				
			||||||
    divorce_year smallint NULL,
 | 
					    divorce_year smallint NULL,
 | 
				
			||||||
    divorce_month smallint NULL,
 | 
					    divorce_month smallint NULL,
 | 
				
			||||||
    divorce_day smallint NULL,
 | 
					    divorce_day smallint NULL
 | 
				
			||||||
 | 
					 | 
				
			||||||
    PRIMARY KEY(wife, husband)
 | 
					 | 
				
			||||||
);
 | 
					);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-- Create views
 | 
					-- Create views
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										99
									
								
								geneit_backend/src/controllers/couples_controller.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										99
									
								
								geneit_backend/src/controllers/couples_controller.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,99 @@
 | 
				
			|||||||
 | 
					use crate::controllers::members_controller::RequestDate;
 | 
				
			||||||
 | 
					use crate::controllers::HttpResult;
 | 
				
			||||||
 | 
					use crate::extractors::family_extractor::FamilyInPath;
 | 
				
			||||||
 | 
					use crate::models::{Couple, CoupleState, MemberID};
 | 
				
			||||||
 | 
					use crate::services::{couples_service, members_service};
 | 
				
			||||||
 | 
					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)]
 | 
				
			||||||
 | 
					pub struct CoupleRequest {
 | 
				
			||||||
 | 
					    wife: Option<MemberID>,
 | 
				
			||||||
 | 
					    husband: Option<MemberID>,
 | 
				
			||||||
 | 
					    state: Option<CoupleState>,
 | 
				
			||||||
 | 
					    #[serde(flatten, with = "prefix_wedding")]
 | 
				
			||||||
 | 
					    wedding: Option<RequestDate>,
 | 
				
			||||||
 | 
					    #[serde(flatten, with = "prefix_divorce")]
 | 
				
			||||||
 | 
					    divorce: Option<RequestDate>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					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(())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create a new couple
 | 
				
			||||||
 | 
					pub async fn create(m: FamilyInPath, req: web::Json<CoupleRequest>) -> 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))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,6 +5,7 @@ use actix_web::HttpResponse;
 | 
				
			|||||||
use std::fmt::{Debug, Display, Formatter};
 | 
					use std::fmt::{Debug, Display, Formatter};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pub mod auth_controller;
 | 
					pub mod auth_controller;
 | 
				
			||||||
 | 
					pub mod couples_controller;
 | 
				
			||||||
pub mod families_controller;
 | 
					pub mod families_controller;
 | 
				
			||||||
pub mod members_controller;
 | 
					pub mod members_controller;
 | 
				
			||||||
pub mod photos_controller;
 | 
					pub mod photos_controller;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -6,8 +6,8 @@ use actix_web::{web, App, HttpServer};
 | 
				
			|||||||
use geneit_backend::app_config::AppConfig;
 | 
					use geneit_backend::app_config::AppConfig;
 | 
				
			||||||
use geneit_backend::connections::s3_connection;
 | 
					use geneit_backend::connections::s3_connection;
 | 
				
			||||||
use geneit_backend::controllers::{
 | 
					use geneit_backend::controllers::{
 | 
				
			||||||
    auth_controller, families_controller, members_controller, photos_controller, server_controller,
 | 
					    auth_controller, couples_controller, families_controller, members_controller,
 | 
				
			||||||
    users_controller,
 | 
					    photos_controller, server_controller, users_controller,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
 | 
					
 | 
				
			||||||
#[actix_web::main]
 | 
					#[actix_web::main]
 | 
				
			||||||
@@ -162,6 +162,12 @@ async fn main() -> std::io::Result<()> {
 | 
				
			|||||||
                "/family/{id}/member/{member_id}/photo",
 | 
					                "/family/{id}/member/{member_id}/photo",
 | 
				
			||||||
                web::delete().to(members_controller::remove_photo),
 | 
					                web::delete().to(members_controller::remove_photo),
 | 
				
			||||||
            )
 | 
					            )
 | 
				
			||||||
 | 
					            // Couples controller
 | 
				
			||||||
 | 
					            .route(
 | 
				
			||||||
 | 
					                "/family/{id}/couple/create",
 | 
				
			||||||
 | 
					                web::post().to(couples_controller::create),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            // Photos controller
 | 
				
			||||||
            .route(
 | 
					            .route(
 | 
				
			||||||
                "/photo/{id}",
 | 
					                "/photo/{id}",
 | 
				
			||||||
                web::get().to(photos_controller::get_full_size),
 | 
					                web::get().to(photos_controller::get_full_size),
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,5 @@
 | 
				
			|||||||
use crate::app_config::AppConfig;
 | 
					use crate::app_config::AppConfig;
 | 
				
			||||||
use crate::schema::{families, members, memberships, photos, users};
 | 
					use crate::schema::{couples, families, members, memberships, photos, users};
 | 
				
			||||||
use crate::utils::crypt_utils::sha256;
 | 
					use crate::utils::crypt_utils::sha256;
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -297,3 +297,105 @@ pub struct NewMember {
 | 
				
			|||||||
    pub time_create: i64,
 | 
					    pub time_create: i64,
 | 
				
			||||||
    pub time_update: i64,
 | 
					    pub time_update: i64,
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Member ID holder
 | 
				
			||||||
 | 
					#[derive(Debug, Clone, Copy, serde::Serialize, serde::Deserialize, Eq, PartialEq, Hash)]
 | 
				
			||||||
 | 
					pub struct CoupleID(pub i32);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(serde::Serialize, serde::Deserialize)]
 | 
				
			||||||
 | 
					pub enum CoupleState {
 | 
				
			||||||
 | 
					    #[serde(rename = "N")]
 | 
				
			||||||
 | 
					    None,
 | 
				
			||||||
 | 
					    #[serde(rename = "E")]
 | 
				
			||||||
 | 
					    Engaged,
 | 
				
			||||||
 | 
					    #[serde(rename = "M")]
 | 
				
			||||||
 | 
					    Married,
 | 
				
			||||||
 | 
					    #[serde(rename = "D")]
 | 
				
			||||||
 | 
					    Divorced,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl CoupleState {
 | 
				
			||||||
 | 
					    pub fn as_str(&self) -> &str {
 | 
				
			||||||
 | 
					        match self {
 | 
				
			||||||
 | 
					            CoupleState::None => "N",
 | 
				
			||||||
 | 
					            CoupleState::Engaged => "E",
 | 
				
			||||||
 | 
					            CoupleState::Married => "M",
 | 
				
			||||||
 | 
					            CoupleState::Divorced => "D",
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn parse_str(s: &str) -> Option<Self> {
 | 
				
			||||||
 | 
					        serde_json::from_str(s).ok()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Queryable, Debug, serde::Serialize)]
 | 
				
			||||||
 | 
					pub struct Couple {
 | 
				
			||||||
 | 
					    id: i32,
 | 
				
			||||||
 | 
					    family_id: i32,
 | 
				
			||||||
 | 
					    wife: Option<i32>,
 | 
				
			||||||
 | 
					    husband: Option<i32>,
 | 
				
			||||||
 | 
					    state: Option<String>,
 | 
				
			||||||
 | 
					    photo_id: Option<i32>,
 | 
				
			||||||
 | 
					    time_create: i64,
 | 
				
			||||||
 | 
					    pub time_update: i64,
 | 
				
			||||||
 | 
					    pub wedding_year: Option<i16>,
 | 
				
			||||||
 | 
					    pub wedding_month: Option<i16>,
 | 
				
			||||||
 | 
					    pub wedding_day: Option<i16>,
 | 
				
			||||||
 | 
					    pub divorce_year: Option<i16>,
 | 
				
			||||||
 | 
					    pub divorce_month: Option<i16>,
 | 
				
			||||||
 | 
					    pub divorce_day: Option<i16>,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					impl Couple {
 | 
				
			||||||
 | 
					    pub fn id(&self) -> CoupleID {
 | 
				
			||||||
 | 
					        CoupleID(self.id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn family_id(&self) -> FamilyID {
 | 
				
			||||||
 | 
					        FamilyID(self.family_id)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn state(&self) -> Option<CoupleState> {
 | 
				
			||||||
 | 
					        self.state
 | 
				
			||||||
 | 
					            .as_deref()
 | 
				
			||||||
 | 
					            .map(CoupleState::parse_str)
 | 
				
			||||||
 | 
					            .unwrap_or_default()
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_state(&mut self, s: Option<CoupleState>) {
 | 
				
			||||||
 | 
					        self.state = s.map(|s| s.as_str().to_string())
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_wife(&mut self, s: Option<MemberID>) {
 | 
				
			||||||
 | 
					        self.wife = s.map(|s| s.0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn wife(&self) -> Option<MemberID> {
 | 
				
			||||||
 | 
					        self.wife.map(MemberID)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_husband(&mut self, s: Option<MemberID>) {
 | 
				
			||||||
 | 
					        self.husband = s.map(|s| s.0)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn husband(&self) -> Option<MemberID> {
 | 
				
			||||||
 | 
					        self.husband.map(MemberID)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn set_photo_id(&mut self, p: Option<PhotoID>) {
 | 
				
			||||||
 | 
					        self.photo_id = p.map(|p| p.0);
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    pub fn photo_id(&self) -> Option<PhotoID> {
 | 
				
			||||||
 | 
					        self.photo_id.map(PhotoID)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					#[derive(Insertable)]
 | 
				
			||||||
 | 
					#[diesel(table_name = couples)]
 | 
				
			||||||
 | 
					pub struct NewCouple {
 | 
				
			||||||
 | 
					    pub family_id: i32,
 | 
				
			||||||
 | 
					    pub time_create: i64,
 | 
				
			||||||
 | 
					    pub time_update: i64,
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,10 +1,15 @@
 | 
				
			|||||||
// @generated automatically by Diesel CLI.
 | 
					// @generated automatically by Diesel CLI.
 | 
				
			||||||
 | 
					
 | 
				
			||||||
diesel::table! {
 | 
					diesel::table! {
 | 
				
			||||||
    couples (wife, husband) {
 | 
					    couples (id) {
 | 
				
			||||||
        wife -> Int4,
 | 
					        id -> Int4,
 | 
				
			||||||
        husband -> Int4,
 | 
					        family_id -> Int4,
 | 
				
			||||||
 | 
					        wife -> Nullable<Int4>,
 | 
				
			||||||
 | 
					        husband -> Nullable<Int4>,
 | 
				
			||||||
 | 
					        state -> Nullable<Varchar>,
 | 
				
			||||||
        photo_id -> Nullable<Int4>,
 | 
					        photo_id -> Nullable<Int4>,
 | 
				
			||||||
 | 
					        time_create -> Int8,
 | 
				
			||||||
 | 
					        time_update -> Int8,
 | 
				
			||||||
        wedding_year -> Nullable<Int2>,
 | 
					        wedding_year -> Nullable<Int2>,
 | 
				
			||||||
        wedding_month -> Nullable<Int2>,
 | 
					        wedding_month -> Nullable<Int2>,
 | 
				
			||||||
        wedding_day -> Nullable<Int2>,
 | 
					        wedding_day -> Nullable<Int2>,
 | 
				
			||||||
@@ -90,6 +95,7 @@ diesel::table! {
 | 
				
			|||||||
    }
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					diesel::joinable!(couples -> families (family_id));
 | 
				
			||||||
diesel::joinable!(couples -> photos (photo_id));
 | 
					diesel::joinable!(couples -> photos (photo_id));
 | 
				
			||||||
diesel::joinable!(members -> families (family_id));
 | 
					diesel::joinable!(members -> families (family_id));
 | 
				
			||||||
diesel::joinable!(members -> photos (photo_id));
 | 
					diesel::joinable!(members -> photos (photo_id));
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										124
									
								
								geneit_backend/src/services/couples_service.rs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										124
									
								
								geneit_backend/src/services/couples_service.rs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,124 @@
 | 
				
			|||||||
 | 
					use crate::connections::db_connection;
 | 
				
			||||||
 | 
					use crate::models::{Couple, CoupleID, FamilyID, MemberID, NewCouple};
 | 
				
			||||||
 | 
					use crate::schema::couples;
 | 
				
			||||||
 | 
					use crate::services::photos_service;
 | 
				
			||||||
 | 
					use crate::utils::time_utils::time;
 | 
				
			||||||
 | 
					use diesel::prelude::*;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Create a new couple
 | 
				
			||||||
 | 
					pub async fn create(family_id: FamilyID) -> anyhow::Result<Couple> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        let res: Couple = diesel::insert_into(couples::table)
 | 
				
			||||||
 | 
					            .values(&NewCouple {
 | 
				
			||||||
 | 
					                family_id: family_id.0,
 | 
				
			||||||
 | 
					                time_create: time() as i64,
 | 
				
			||||||
 | 
					                time_update: time() as i64,
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            .get_result(conn)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(res)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get the information of a couple
 | 
				
			||||||
 | 
					pub async fn get_by_id(id: CoupleID) -> anyhow::Result<Couple> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| couples::table.filter(couples::dsl::id.eq(id.0)).first(conn))
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get all the couples of a family
 | 
				
			||||||
 | 
					pub async fn get_all_of_family(id: FamilyID) -> anyhow::Result<Vec<Couple>> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        couples::table
 | 
				
			||||||
 | 
					            .filter(couples::dsl::family_id.eq(id.0))
 | 
				
			||||||
 | 
					            .get_results(conn)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Get all the couples associated to a member
 | 
				
			||||||
 | 
					pub async fn get_all_of_member(id: MemberID) -> anyhow::Result<Vec<Couple>> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        couples::table
 | 
				
			||||||
 | 
					            .filter(
 | 
				
			||||||
 | 
					                couples::dsl::wife
 | 
				
			||||||
 | 
					                    .eq(id.0)
 | 
				
			||||||
 | 
					                    .or(couples::dsl::husband.eq(id.0)),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .get_results(conn)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Check whether a couple with a given id exists or not
 | 
				
			||||||
 | 
					pub async fn exists(family_id: FamilyID, couple_id: CoupleID) -> anyhow::Result<bool> {
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        let count: i64 = couples::table
 | 
				
			||||||
 | 
					            .filter(
 | 
				
			||||||
 | 
					                couples::id
 | 
				
			||||||
 | 
					                    .eq(couple_id.0)
 | 
				
			||||||
 | 
					                    .and(couples::family_id.eq(family_id.0)),
 | 
				
			||||||
 | 
					            )
 | 
				
			||||||
 | 
					            .count()
 | 
				
			||||||
 | 
					            .get_result(conn)?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Ok(count != 0)
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Update the information of a couple
 | 
				
			||||||
 | 
					pub async fn update(couple: &mut Couple) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    couple.time_update = time() as i64;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        diesel::update(couples::dsl::couples.filter(couples::dsl::id.eq(couple.id().0)))
 | 
				
			||||||
 | 
					            .set((
 | 
				
			||||||
 | 
					                couples::dsl::state.eq(couple.state().map(|c| c.as_str().to_string())),
 | 
				
			||||||
 | 
					                couples::dsl::wife.eq(couple.wife().map(|m| m.0)),
 | 
				
			||||||
 | 
					                couples::dsl::husband.eq(couple.husband().map(|m| m.0)),
 | 
				
			||||||
 | 
					                couples::dsl::photo_id.eq(couple.photo_id().map(|p| p.0)),
 | 
				
			||||||
 | 
					                couples::dsl::time_update.eq(couple.time_update),
 | 
				
			||||||
 | 
					                couples::dsl::wedding_year.eq(couple.wedding_year),
 | 
				
			||||||
 | 
					                couples::dsl::wedding_month.eq(couple.wedding_month),
 | 
				
			||||||
 | 
					                couples::dsl::wedding_day.eq(couple.wedding_day),
 | 
				
			||||||
 | 
					                couples::dsl::divorce_year.eq(couple.divorce_year),
 | 
				
			||||||
 | 
					                couples::dsl::divorce_month.eq(couple.divorce_month),
 | 
				
			||||||
 | 
					                couples::dsl::divorce_day.eq(couple.divorce_day),
 | 
				
			||||||
 | 
					            ))
 | 
				
			||||||
 | 
					            .execute(conn)
 | 
				
			||||||
 | 
					    })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete a couple photo
 | 
				
			||||||
 | 
					pub async fn remove_photo(couple: &mut Couple) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    match couple.photo_id() {
 | 
				
			||||||
 | 
					        None => {}
 | 
				
			||||||
 | 
					        Some(photo) => {
 | 
				
			||||||
 | 
					            photos_service::delete(photo).await?;
 | 
				
			||||||
 | 
					            couple.set_photo_id(None);
 | 
				
			||||||
 | 
					            update(couple).await?;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete a couple
 | 
				
			||||||
 | 
					pub async fn delete(couple: &mut Couple) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    remove_photo(couple).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    // Remove the couple
 | 
				
			||||||
 | 
					    db_connection::execute(|conn| {
 | 
				
			||||||
 | 
					        diesel::delete(couples::dsl::couples.filter(couples::dsl::id.eq(couple.id().0)))
 | 
				
			||||||
 | 
					            .execute(conn)
 | 
				
			||||||
 | 
					    })?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/// Delete all the couples of a family
 | 
				
			||||||
 | 
					pub async fn delete_all_family(family_id: FamilyID) -> anyhow::Result<()> {
 | 
				
			||||||
 | 
					    for mut m in get_all_of_family(family_id).await? {
 | 
				
			||||||
 | 
					        delete(&mut m).await?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    Ok(())
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -5,7 +5,7 @@ use crate::models::{
 | 
				
			|||||||
    Family, FamilyID, FamilyMembership, Membership, NewFamily, NewMembership, UserID,
 | 
					    Family, FamilyID, FamilyMembership, Membership, NewFamily, NewMembership, UserID,
 | 
				
			||||||
};
 | 
					};
 | 
				
			||||||
use crate::schema::{families, memberships};
 | 
					use crate::schema::{families, memberships};
 | 
				
			||||||
use crate::services::{members_service, users_service};
 | 
					use crate::services::{couples_service, members_service, users_service};
 | 
				
			||||||
use crate::utils::string_utils::rand_str;
 | 
					use crate::utils::string_utils::rand_str;
 | 
				
			||||||
use crate::utils::time_utils::time;
 | 
					use crate::utils::time_utils::time;
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
@@ -183,7 +183,8 @@ pub async fn update_family(family: &Family) -> anyhow::Result<()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Delete a family
 | 
					/// Delete a family
 | 
				
			||||||
pub async fn delete_family(family_id: FamilyID) -> anyhow::Result<()> {
 | 
					pub async fn delete_family(family_id: FamilyID) -> anyhow::Result<()> {
 | 
				
			||||||
    // TODO : delete couples
 | 
					    // Delete all family couples
 | 
				
			||||||
 | 
					    couples_service::delete_all_family(family_id).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    // Remove all family members
 | 
					    // Remove all family members
 | 
				
			||||||
    members_service::delete_all_family(family_id).await?;
 | 
					    members_service::delete_all_family(family_id).await?;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
use crate::connections::db_connection;
 | 
					use crate::connections::db_connection;
 | 
				
			||||||
use crate::models::{FamilyID, Member, MemberID, NewMember};
 | 
					use crate::models::{FamilyID, Member, MemberID, NewMember};
 | 
				
			||||||
use crate::schema::members;
 | 
					use crate::schema::members;
 | 
				
			||||||
use crate::services::photos_service;
 | 
					use crate::services::{couples_service, photos_service};
 | 
				
			||||||
use crate::utils::time_utils::time;
 | 
					use crate::utils::time_utils::time;
 | 
				
			||||||
use diesel::prelude::*;
 | 
					use diesel::prelude::*;
 | 
				
			||||||
use diesel::RunQueryDsl;
 | 
					use diesel::RunQueryDsl;
 | 
				
			||||||
@@ -102,7 +102,16 @@ pub async fn remove_photo(member: &mut Member) -> anyhow::Result<()> {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
/// Delete a member
 | 
					/// Delete a member
 | 
				
			||||||
pub async fn delete(member: &mut Member) -> anyhow::Result<()> {
 | 
					pub async fn delete(member: &mut Member) -> anyhow::Result<()> {
 | 
				
			||||||
    // TODO : remove associated couple
 | 
					    // Remove associated couple
 | 
				
			||||||
 | 
					    for mut c in couples_service::get_all_of_member(member.id()).await? {
 | 
				
			||||||
 | 
					        // Check if only one person is attached to the couple
 | 
				
			||||||
 | 
					        // i.e. if the current member is the last person attached to the couple
 | 
				
			||||||
 | 
					        if c.wife().is_some() && c.husband().is_some() {
 | 
				
			||||||
 | 
					            continue;
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        couples_service::delete(&mut c).await?;
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    remove_photo(member).await?;
 | 
					    remove_photo(member).await?;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,5 +1,6 @@
 | 
				
			|||||||
//! # Backend services
 | 
					//! # Backend services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					pub mod couples_service;
 | 
				
			||||||
pub mod families_service;
 | 
					pub mod families_service;
 | 
				
			||||||
pub mod login_token_service;
 | 
					pub mod login_token_service;
 | 
				
			||||||
pub mod mail_service;
 | 
					pub mod mail_service;
 | 
				
			||||||
 
 | 
				
			|||||||
		Reference in New Issue
	
	Block a user