From 9bef82126aea0b3e2f994e80ceda30cfdc089bd4 Mon Sep 17 00:00:00 2001 From: Franklin Date: Sat, 11 Mar 2023 10:40:52 -0400 Subject: [PATCH] Added renames --- Cargo.lock | 1 + Cargo.toml | 1 + src/domain/filters/property.rs | 19 ++++--- src/domain/mod.rs | 3 +- src/domain/money/mod.rs | 85 ------------------------------ src/domain/property_details/mod.rs | 35 +++++++----- src/dto/joiners/mod.rs | 0 src/dto/mod.rs | 3 +- src/dto/payload/agent.rs | 38 +++++++++++++ src/dto/payload/property.rs | 59 ++++++++++++++++++++- 10 files changed, 134 insertions(+), 110 deletions(-) delete mode 100644 src/domain/money/mod.rs create mode 100644 src/dto/joiners/mod.rs diff --git a/Cargo.lock b/Cargo.lock index 39dcf7d..1477124 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -848,6 +848,7 @@ dependencies = [ "chrono-tz", "format_num", "serde", + "serde_json", "sqlx", "uuid", ] diff --git a/Cargo.toml b/Cargo.toml index 5c43cb6..5514ccb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,6 +9,7 @@ edition = "2021" chrono = { version = "0.4.23", features = [ "serde" ] } chrono-tz = "0.8" serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0.88" uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] } format_num = "0.1.0" sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ] } diff --git a/src/domain/filters/property.rs b/src/domain/filters/property.rs index 88464e1..817e88e 100644 --- a/src/domain/filters/property.rs +++ b/src/domain/filters/property.rs @@ -1,8 +1,11 @@ use chrono::{DateTime, Utc}; use serde::{Serialize, Deserialize}; +use uuid::Uuid; + +use crate::domain::{property_details::ListingType}; -#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] pub enum PropertyFilter { // By Time Before(DateTime), @@ -10,15 +13,15 @@ pub enum PropertyFilter { // By Word matching Title(String), + Description(String), + + Location(Uuid), // By cost - CheaperThan(u64), - MoreExpensiveThan(u64), - - // By Contract type - ContractType(String), + CheaperThan(ListingType), + MoreExpensiveThan(ListingType), // By Size - BiggerOrEqualTo(u32), - SmallerOrEqualTo(u32), + BiggerOrEqualTo(f32), + SmallerOrEqualTo(f32), } \ No newline at end of file diff --git a/src/domain/mod.rs b/src/domain/mod.rs index 4cafa6c..a236853 100644 --- a/src/domain/mod.rs +++ b/src/domain/mod.rs @@ -3,5 +3,4 @@ pub mod property; pub mod location; pub mod contact_info; pub mod property_details; -pub mod filters; -pub mod money; \ No newline at end of file +pub mod filters; \ No newline at end of file diff --git a/src/domain/money/mod.rs b/src/domain/money/mod.rs deleted file mode 100644 index 7523398..0000000 --- a/src/domain/money/mod.rs +++ /dev/null @@ -1,85 +0,0 @@ -use std::fmt::Display; - -use format_num::NumberFormat; -use serde::{Serialize, Deserialize}; -use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError}; - -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)] -pub enum Currency { - #[default] - Usd, - Dop, - Eur, -} - -#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, PartialOrd)] -pub struct Money { - pub amount: f64, - pub currency: Currency, -} - -impl Display for Money { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - let number_formatter = NumberFormat::new(); - let amount_fmted = number_formatter.format(".2f", self.amount); - match self.currency { - Currency::Usd => write!(f, "US${}", amount_fmted), - Currency::Dop => write!(f, "RD${}", amount_fmted), - Currency::Eur => write!(f, "EUR€{}", amount_fmted) - } - } -} - -impl sqlx::Encode<'_, Postgres> for Currency { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = bincode::serialize(self).unwrap(); - as sqlx::Encode>::encode(encoded_value, buf) - } -} - -impl sqlx::Decode<'_, Postgres> for Currency { - fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_bytes()?; - match bincode::deserialize(column) { - Ok(listing_state) => Ok(listing_state), - Err(error) => Err(error), - } - } -} - -impl sqlx::Type for Currency { - fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("bytea") - } - - fn compatible(ty: &::TypeInfo) -> bool { - *ty == Self::type_info() - } -} - -impl sqlx::Encode<'_, Postgres> for Money { - fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = bincode::serialize(self).unwrap(); - as sqlx::Encode>::encode(encoded_value, buf) - } -} - -impl sqlx::Decode<'_, Postgres> for Money { - fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_bytes()?; - match bincode::deserialize(column) { - Ok(listing_state) => Ok(listing_state), - Err(error) => Err(error), - } - } -} - -impl sqlx::Type for Money { - fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("bytea") - } - - fn compatible(ty: &::TypeInfo) -> bool { - *ty == Self::type_info() - } -} \ No newline at end of file diff --git a/src/domain/property_details/mod.rs b/src/domain/property_details/mod.rs index 210785c..2c5c78e 100644 --- a/src/domain/property_details/mod.rs +++ b/src/domain/property_details/mod.rs @@ -1,9 +1,9 @@ +use std::fmt::Display; + use serde::{Serialize, Deserialize}; use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError}; use uuid::Uuid; -use super::money::Money; - #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Default)] pub struct PropertyDetails { @@ -20,14 +20,23 @@ pub struct PropertyDetails { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] pub enum ListingType { - Rent(Money), - Sale(Money), + Rent(f64), + Sale(f64), /// Sale first, Rent Second - Both(Money, Money), + Both(f64, f64), } impl Default for ListingType { fn default() -> Self { - Self::Sale(Money::default()) + Self::Sale(0.0) + } +} +impl Display for ListingType { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ListingType::Rent(amount) => write!(f, "rent {amount}"), + ListingType::Sale(amount) => write!(f, "sale {amount}"), + ListingType::Both(sale_amount, rent_amount) => write!(f, "both {sale_amount} {rent_amount}"), + } } } @@ -69,24 +78,24 @@ impl sqlx::Type for Photos { impl sqlx::Encode<'_, Postgres> for ListingType { fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull { - let encoded_value = bincode::serialize(self).unwrap(); - as sqlx::Encode>::encode(encoded_value, buf) + let encoded_value = serde_json::to_string(self).unwrap(); + <&str as sqlx::Encode>::encode(encoded_value.as_str(), buf) } } impl sqlx::Decode<'_, Postgres> for ListingType { fn decode(value: PgValueRef<'_>) -> Result { - let column = value.as_bytes()?; - match bincode::deserialize(column) { - Ok(listing_state) => Ok(listing_state), - Err(error) => Err(error), + let column = value.as_str()?; + match serde_json::from_str(column) { + Ok(val) => Ok(val), + Err(error) => Err(Box::new(error)), } } } impl sqlx::Type for ListingType { fn type_info() -> PgTypeInfo { - PgTypeInfo::with_name("bytea") + PgTypeInfo::with_name("VARCHAR") } fn compatible(ty: &::TypeInfo) -> bool { diff --git a/src/dto/joiners/mod.rs b/src/dto/joiners/mod.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/dto/mod.rs b/src/dto/mod.rs index aa7d191..0762f6e 100644 --- a/src/dto/mod.rs +++ b/src/dto/mod.rs @@ -1,3 +1,4 @@ pub mod property; pub mod agent; -pub mod payload; \ No newline at end of file +pub mod payload; +pub mod joiners; \ No newline at end of file diff --git a/src/dto/payload/agent.rs b/src/dto/payload/agent.rs index ae48682..7450256 100644 --- a/src/dto/payload/agent.rs +++ b/src/dto/payload/agent.rs @@ -1,4 +1,5 @@ use serde::{Serialize, Deserialize}; +use uuid::Uuid; use crate::domain::{agent::Agent, contact_info::ContactInformation}; @@ -10,12 +11,16 @@ pub struct AgentWithContactInfo { #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] pub struct NewAgentPayload { + #[serde(rename = "fullName")] pub full_name: String, + #[serde(rename = "phoneNumber")] pub phone_number: String, // Optional fields pub email: Option, + #[serde(rename = "profilePictureUrl")] pub profile_picture_url: Option, + #[serde(rename = "defaultMessage")] pub default_message: Option, } impl From for AgentWithContactInfo { @@ -34,3 +39,36 @@ impl From for AgentWithContactInfo { } } } + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] +pub struct UpdateAgentPayload { + pub id: Uuid, + #[serde(rename = "phoneNumber")] + pub phone_number: Option, + pub email: Option, + #[serde(rename = "profilePictureUrl")] + pub profile_picture_url: Option, + #[serde(rename = "defaultMessage")] + pub default_message: Option, +} + +impl UpdateAgentPayload { + pub fn update_contact_info(self, contact_info: &mut ContactInformation) { + match self.phone_number { + Some(phone_number) => contact_info.phone_number = phone_number, + None => {}, + }; + match self.email { + Some(_) => contact_info.email = self.email, + None => {}, + }; + match self.profile_picture_url { + Some(_) => contact_info.profile_picture_url = self.profile_picture_url, + None => {}, + }; + match self.default_message { + Some(_) => contact_info.default_message = self.default_message, + None => {}, + }; + } +} \ No newline at end of file diff --git a/src/dto/payload/property.rs b/src/dto/payload/property.rs index af89dad..db2d040 100644 --- a/src/dto/payload/property.rs +++ b/src/dto/payload/property.rs @@ -1,7 +1,8 @@ +use chrono::Utc; use serde::{Deserialize, Serialize}; use uuid::Uuid; -use crate::domain::{property_details::{ListingType, Photos, PropertyDetails}, property::Property}; +use crate::domain::{property_details::{ListingType, Photos, PropertyDetails}, property::{Property, ListingState}}; #[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] pub struct PropertyWithDetails { @@ -39,4 +40,60 @@ impl From for PropertyWithDetails { }, } } +} + +#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)] +pub struct UpdateListingPayload { + #[serde(rename = "propertyId")] + pub property_id: Uuid, + pub title: Option, + pub description: Option, + pub meters: Option, + #[serde(rename = "listingType")] + pub listing_type: Option, + #[serde(rename = "photoUrls")] + pub photo_urls: Option, + #[serde(rename = "locationId")] + pub location_id: Option, + #[serde(rename = "agentId")] + pub agent_id: Option, + pub state: Option, +} + +impl UpdateListingPayload { + pub fn update_listing(self, property: &mut Property, details: &mut PropertyDetails) { + match self.title { + Some(title) => property.title = title, + None => {}, + }; + match self.description { + Some(description) => property.description = description, + None => {}, + }; + match self.meters { + Some(meters) => details.meters = meters, + None => {}, + }; + match self.listing_type { + Some(listing_type) => details.listing_type = listing_type, + None => {}, + }; + match self.photo_urls { + Some(photo_urls) => details.photo_urls = photo_urls, + None => {}, + }; + match self.location_id { + Some(location_id) => details.location_id = location_id, + None => {}, + }; + match self.agent_id { + Some(agent_id) => property.agent_id = agent_id, + None => {}, + }; + match self.state { + Some(state) => property.state = state, + None => {}, + }; + property.last_updated = Utc::now(); + } } \ No newline at end of file