Added renames
This commit is contained in:
parent
6b2e978eec
commit
9bef82126a
|
@ -848,6 +848,7 @@ dependencies = [
|
||||||
"chrono-tz",
|
"chrono-tz",
|
||||||
"format_num",
|
"format_num",
|
||||||
"serde",
|
"serde",
|
||||||
|
"serde_json",
|
||||||
"sqlx",
|
"sqlx",
|
||||||
"uuid",
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
|
@ -9,6 +9,7 @@ edition = "2021"
|
||||||
chrono = { version = "0.4.23", features = [ "serde" ] }
|
chrono = { version = "0.4.23", features = [ "serde" ] }
|
||||||
chrono-tz = "0.8"
|
chrono-tz = "0.8"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
|
serde_json = "1.0.88"
|
||||||
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }
|
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics", "serde"] }
|
||||||
format_num = "0.1.0"
|
format_num = "0.1.0"
|
||||||
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ] }
|
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ] }
|
||||||
|
|
|
@ -1,8 +1,11 @@
|
||||||
use chrono::{DateTime, Utc};
|
use chrono::{DateTime, Utc};
|
||||||
use serde::{Serialize, Deserialize};
|
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 {
|
pub enum PropertyFilter {
|
||||||
// By Time
|
// By Time
|
||||||
Before(DateTime<Utc>),
|
Before(DateTime<Utc>),
|
||||||
|
@ -10,15 +13,15 @@ pub enum PropertyFilter {
|
||||||
|
|
||||||
// By Word matching
|
// By Word matching
|
||||||
Title(String),
|
Title(String),
|
||||||
|
Description(String),
|
||||||
|
|
||||||
|
Location(Uuid),
|
||||||
|
|
||||||
// By cost
|
// By cost
|
||||||
CheaperThan(u64),
|
CheaperThan(ListingType),
|
||||||
MoreExpensiveThan(u64),
|
MoreExpensiveThan(ListingType),
|
||||||
|
|
||||||
// By Contract type
|
|
||||||
ContractType(String),
|
|
||||||
|
|
||||||
// By Size
|
// By Size
|
||||||
BiggerOrEqualTo(u32),
|
BiggerOrEqualTo(f32),
|
||||||
SmallerOrEqualTo(u32),
|
SmallerOrEqualTo(f32),
|
||||||
}
|
}
|
|
@ -4,4 +4,3 @@ pub mod location;
|
||||||
pub mod contact_info;
|
pub mod contact_info;
|
||||||
pub mod property_details;
|
pub mod property_details;
|
||||||
pub mod filters;
|
pub mod filters;
|
||||||
pub mod money;
|
|
|
@ -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 serde::{Serialize, Deserialize};
|
||||||
use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError};
|
use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError};
|
||||||
use uuid::Uuid;
|
use uuid::Uuid;
|
||||||
|
|
||||||
use super::money::Money;
|
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Default)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd, Default)]
|
||||||
pub struct PropertyDetails {
|
pub struct PropertyDetails {
|
||||||
|
@ -20,14 +20,23 @@ pub struct PropertyDetails {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
||||||
pub enum ListingType {
|
pub enum ListingType {
|
||||||
Rent(Money),
|
Rent(f64),
|
||||||
Sale(Money),
|
Sale(f64),
|
||||||
/// Sale first, Rent Second
|
/// Sale first, Rent Second
|
||||||
Both(Money, Money),
|
Both(f64, f64),
|
||||||
}
|
}
|
||||||
impl Default for ListingType {
|
impl Default for ListingType {
|
||||||
fn default() -> Self {
|
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 {
|
impl sqlx::Encode<'_, Postgres> for ListingType {
|
||||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||||
let encoded_value = bincode::serialize(self).unwrap();
|
let encoded_value = serde_json::to_string(self).unwrap();
|
||||||
<Vec<u8> as sqlx::Encode<Postgres>>::encode(encoded_value, buf)
|
<&str as sqlx::Encode<Postgres>>::encode(encoded_value.as_str(), buf)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sqlx::Decode<'_, Postgres> for ListingType {
|
impl sqlx::Decode<'_, Postgres> for ListingType {
|
||||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||||
let column = value.as_bytes()?;
|
let column = value.as_str()?;
|
||||||
match bincode::deserialize(column) {
|
match serde_json::from_str(column) {
|
||||||
Ok(listing_state) => Ok(listing_state),
|
Ok(val) => Ok(val),
|
||||||
Err(error) => Err(error),
|
Err(error) => Err(Box::new(error)),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl sqlx::Type<Postgres> for ListingType {
|
impl sqlx::Type<Postgres> for ListingType {
|
||||||
fn type_info() -> PgTypeInfo {
|
fn type_info() -> PgTypeInfo {
|
||||||
PgTypeInfo::with_name("bytea")
|
PgTypeInfo::with_name("VARCHAR")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||||
|
|
|
@ -1,3 +1,4 @@
|
||||||
pub mod property;
|
pub mod property;
|
||||||
pub mod agent;
|
pub mod agent;
|
||||||
pub mod payload;
|
pub mod payload;
|
||||||
|
pub mod joiners;
|
|
@ -1,4 +1,5 @@
|
||||||
use serde::{Serialize, Deserialize};
|
use serde::{Serialize, Deserialize};
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use crate::domain::{agent::Agent, contact_info::ContactInformation};
|
use crate::domain::{agent::Agent, contact_info::ContactInformation};
|
||||||
|
|
||||||
|
@ -10,12 +11,16 @@ pub struct AgentWithContactInfo {
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct NewAgentPayload {
|
pub struct NewAgentPayload {
|
||||||
|
#[serde(rename = "fullName")]
|
||||||
pub full_name: String,
|
pub full_name: String,
|
||||||
|
#[serde(rename = "phoneNumber")]
|
||||||
pub phone_number: String,
|
pub phone_number: String,
|
||||||
|
|
||||||
// Optional fields
|
// Optional fields
|
||||||
pub email: Option<String>,
|
pub email: Option<String>,
|
||||||
|
#[serde(rename = "profilePictureUrl")]
|
||||||
pub profile_picture_url: Option<String>,
|
pub profile_picture_url: Option<String>,
|
||||||
|
#[serde(rename = "defaultMessage")]
|
||||||
pub default_message: Option<String>,
|
pub default_message: Option<String>,
|
||||||
}
|
}
|
||||||
impl From<NewAgentPayload> for AgentWithContactInfo {
|
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 serde::{Deserialize, Serialize};
|
||||||
use uuid::Uuid;
|
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)]
|
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, PartialOrd)]
|
||||||
pub struct PropertyWithDetails {
|
pub struct PropertyWithDetails {
|
||||||
|
@ -40,3 +41,59 @@ 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