Added renames
This commit is contained in:
parent
6b2e978eec
commit
9bef82126a
|
@ -848,6 +848,7 @@ dependencies = [
|
|||
"chrono-tz",
|
||||
"format_num",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"sqlx",
|
||||
"uuid",
|
||||
]
|
||||
|
|
|
@ -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" ] }
|
||||
|
|
|
@ -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<Utc>),
|
||||
|
@ -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),
|
||||
}
|
|
@ -3,5 +3,4 @@ pub mod property;
|
|||
pub mod location;
|
||||
pub mod contact_info;
|
||||
pub mod property_details;
|
||||
pub mod filters;
|
||||
pub mod money;
|
||||
pub mod filters;
|
|
@ -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();
|
||||
<Vec<u8> as sqlx::Encode<Postgres>>::encode(encoded_value, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlx::Decode<'_, Postgres> for Currency {
|
||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||
let column = value.as_bytes()?;
|
||||
match bincode::deserialize(column) {
|
||||
Ok(listing_state) => Ok(listing_state),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlx::Type<Postgres> for Currency {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("bytea")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::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();
|
||||
<Vec<u8> as sqlx::Encode<Postgres>>::encode(encoded_value, buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlx::Decode<'_, Postgres> for Money {
|
||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||
let column = value.as_bytes()?;
|
||||
match bincode::deserialize(column) {
|
||||
Ok(listing_state) => Ok(listing_state),
|
||||
Err(error) => Err(error),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlx::Type<Postgres> for Money {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("bytea")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||
*ty == Self::type_info()
|
||||
}
|
||||
}
|
|
@ -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<Postgres> for Photos {
|
|||
|
||||
impl sqlx::Encode<'_, Postgres> for ListingType {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
let encoded_value = bincode::serialize(self).unwrap();
|
||||
<Vec<u8> as sqlx::Encode<Postgres>>::encode(encoded_value, buf)
|
||||
let encoded_value = serde_json::to_string(self).unwrap();
|
||||
<&str as sqlx::Encode<Postgres>>::encode(encoded_value.as_str(), buf)
|
||||
}
|
||||
}
|
||||
|
||||
impl sqlx::Decode<'_, Postgres> for ListingType {
|
||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||
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<Postgres> for ListingType {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("bytea")
|
||||
PgTypeInfo::with_name("VARCHAR")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
pub mod property;
|
||||
pub mod agent;
|
||||
pub mod payload;
|
||||
pub mod payload;
|
||||
pub mod joiners;
|
|
@ -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<String>,
|
||||
#[serde(rename = "profilePictureUrl")]
|
||||
pub profile_picture_url: Option<String>,
|
||||
#[serde(rename = "defaultMessage")]
|
||||
pub default_message: Option<String>,
|
||||
}
|
||||
impl From<NewAgentPayload> for AgentWithContactInfo {
|
||||
|
@ -34,3 +39,36 @@ impl From<NewAgentPayload> for AgentWithContactInfo {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub struct UpdateAgentPayload {
|
||||
pub id: Uuid,
|
||||
#[serde(rename = "phoneNumber")]
|
||||
pub phone_number: Option<String>,
|
||||
pub email: Option<String>,
|
||||
#[serde(rename = "profilePictureUrl")]
|
||||
pub profile_picture_url: Option<String>,
|
||||
#[serde(rename = "defaultMessage")]
|
||||
pub default_message: Option<String>,
|
||||
}
|
||||
|
||||
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 => {},
|
||||
};
|
||||
}
|
||||
}
|
|
@ -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<NewPropertyPayload> for PropertyWithDetails {
|
|||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
||||
pub struct UpdateListingPayload {
|
||||
#[serde(rename = "propertyId")]
|
||||
pub property_id: Uuid,
|
||||
pub title: Option<String>,
|
||||
pub description: Option<String>,
|
||||
pub meters: Option<f32>,
|
||||
#[serde(rename = "listingType")]
|
||||
pub listing_type: Option<ListingType>,
|
||||
#[serde(rename = "photoUrls")]
|
||||
pub photo_urls: Option<Photos>,
|
||||
#[serde(rename = "locationId")]
|
||||
pub location_id: Option<Uuid>,
|
||||
#[serde(rename = "agentId")]
|
||||
pub agent_id: Option<Uuid>,
|
||||
pub state: Option<ListingState>,
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue