Added arrangement, more property fields, and impls
This commit is contained in:
parent
1b4600ec21
commit
8de10c4e3b
56
src/domain/arrangement/impls.rs
Normal file
56
src/domain/arrangement/impls.rs
Normal file
@ -0,0 +1,56 @@
|
||||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError};
|
||||
|
||||
use crate::domain::error::FromStrError;
|
||||
|
||||
use super::ArrangementType;
|
||||
|
||||
impl Display for ArrangementType {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
ArrangementType::Rent => write!(f, "Rent"),
|
||||
ArrangementType::Sale => write!(f, "Sale"),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for ArrangementType {
|
||||
type Err = FromStrError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Rent" => Ok(Self::Rent),
|
||||
"Sale" => Ok(Self::Sale),
|
||||
_ => Err(FromStrError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Encode<'_, Postgres> for ArrangementType {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
let binding = serde_json::to_string(self).unwrap();
|
||||
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Decode<'_, Postgres> for ArrangementType {
|
||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||
let column = value.as_str()?;
|
||||
match serde_json::from_str(column) {
|
||||
Ok(listing_state) => Ok(listing_state),
|
||||
Err(error) => Err(Box::new(error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Type<Postgres> for ArrangementType {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("VARCHAR")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||
*ty == Self::type_info()
|
||||
}
|
||||
}
|
10
src/domain/arrangement/mod.rs
Normal file
10
src/domain/arrangement/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
pub mod impls;
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum ArrangementType {
|
||||
#[default]
|
||||
Rent,
|
||||
Sale,
|
||||
}
|
61
src/domain/format/impls.rs
Normal file
61
src/domain/format/impls.rs
Normal file
@ -0,0 +1,61 @@
|
||||
use std::{fmt::Display, str::FromStr};
|
||||
|
||||
use sqlx::{Postgres, postgres::{PgArgumentBuffer, PgValueRef, PgTypeInfo}, encode::IsNull, error::BoxDynError};
|
||||
|
||||
use crate::domain::error::FromStrError;
|
||||
|
||||
use super::FrameFormat;
|
||||
|
||||
|
||||
impl Display for FrameFormat {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
FrameFormat::Landscape => write!(f, "Landscape"),
|
||||
FrameFormat::Instagram => write!(f, "Instagram"),
|
||||
FrameFormat::Portrait => write!(f, "Portrait"),
|
||||
FrameFormat::Square => write!(f, "Square")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromStr for FrameFormat {
|
||||
type Err = FromStrError;
|
||||
|
||||
fn from_str(s: &str) -> Result<Self, Self::Err> {
|
||||
match s {
|
||||
"Landscape" => Ok(Self::Landscape),
|
||||
"Instagram" => Ok(Self::Instagram),
|
||||
"Portrait" => Ok(Self::Portrait),
|
||||
"Square" => Ok(Self::Square),
|
||||
_ => Err(FromStrError)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Encode<'_, Postgres> for FrameFormat {
|
||||
fn encode_by_ref(&self, buf: &mut PgArgumentBuffer) -> IsNull {
|
||||
let binding = self.to_string();
|
||||
<&str as sqlx::Encode<Postgres>>::encode(&binding, buf)
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Decode<'_, Postgres> for FrameFormat {
|
||||
fn decode(value: PgValueRef<'_>) -> Result<Self, BoxDynError> {
|
||||
let column = value.as_str()?;
|
||||
match Self::from_str(column) {
|
||||
Ok(listing_state) => Ok(listing_state),
|
||||
Err(error) => Err(Box::new(error)),
|
||||
}
|
||||
}
|
||||
}
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Type<Postgres> for FrameFormat {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("VARCHAR")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||
*ty == Self::type_info()
|
||||
}
|
||||
}
|
38
src/domain/format/mod.rs
Normal file
38
src/domain/format/mod.rs
Normal file
@ -0,0 +1,38 @@
|
||||
pub mod impls;
|
||||
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
/// Allows realtors to pick the size of each property to fit the carroussel.
|
||||
/// This is easy for agents to use and is better than having them pick what size everything should be.
|
||||
/// All sizes are in w x h in squares
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub enum FrameFormat {
|
||||
/// 2x1
|
||||
#[default]
|
||||
Landscape,
|
||||
/// 2x2
|
||||
Instagram,
|
||||
/// 1x2
|
||||
Portrait,
|
||||
// 1x1
|
||||
Square,
|
||||
}
|
||||
|
||||
impl FrameFormat {
|
||||
pub fn get_width(&self) -> usize {
|
||||
match self {
|
||||
FrameFormat::Landscape => 2,
|
||||
FrameFormat::Instagram => 2,
|
||||
FrameFormat::Portrait => 1,
|
||||
FrameFormat::Square => 1,
|
||||
}
|
||||
}
|
||||
pub fn get_height(&self) -> usize {
|
||||
match self {
|
||||
FrameFormat::Landscape => 1,
|
||||
FrameFormat::Instagram => 2,
|
||||
FrameFormat::Portrait => 2,
|
||||
FrameFormat::Square => 1,
|
||||
}
|
||||
}
|
||||
}
|
@ -11,6 +11,9 @@ pub mod realtor;
|
||||
pub mod thing_pk;
|
||||
pub mod trackable;
|
||||
pub mod view;
|
||||
pub mod format;
|
||||
pub mod price;
|
||||
pub mod arrangement;
|
||||
pub mod project_type;
|
||||
|
||||
pub mod error;
|
||||
pub mod project_type;
|
||||
|
16
src/domain/price.rs
Normal file
16
src/domain/price.rs
Normal file
@ -0,0 +1,16 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::arrangement::ArrangementType;
|
||||
|
||||
|
||||
/// This is what lets the backend know what a property sells for/rents for.
|
||||
/// Store at least one of these per Property.
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, PartialOrd)]
|
||||
pub struct PropertyPrice {
|
||||
#[serde(rename = "propertyId")]
|
||||
pub property_id: Uuid,
|
||||
pub price: f64,
|
||||
pub currency: String,
|
||||
pub arrangement: ArrangementType,
|
||||
}
|
@ -2,7 +2,7 @@ use chrono::{DateTime, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use super::{media::MediaList, property_sale_type::PropertySaleType, property_type::PropertyType};
|
||||
use super::{media::MediaList, property_sale_type::PropertySaleType, property_type::PropertyType, format::FrameFormat};
|
||||
|
||||
/// A property can belong to a project, or not. It should always belong to a realtor.
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, PartialOrd)]
|
||||
@ -17,20 +17,22 @@ pub struct Property {
|
||||
pub property_type: PropertyType,
|
||||
#[serde(rename = "propertySaleType")]
|
||||
pub property_sale_type: PropertySaleType,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub country: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub city: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub district: Option<String>,
|
||||
#[serde(rename = "priceUsd")]
|
||||
pub price_usd: f64,
|
||||
pub country: String,
|
||||
pub city: String,
|
||||
pub district: String,
|
||||
/// This gives the realtor the option to order the projects/properties
|
||||
#[serde(rename = "orderIndex")]
|
||||
pub order_index: i32,
|
||||
#[serde(rename = "thumbnailFormat")]
|
||||
pub thumbnail_format: FrameFormat,
|
||||
/// Amount of rooms in unit
|
||||
pub rooms: i16,
|
||||
/// Amount of bathrooms in unit
|
||||
pub bathrooms: f32,
|
||||
/// In meters squared
|
||||
pub area: f32,
|
||||
#[serde(rename = "parkingSpots")]
|
||||
pub parking_spots: i16,
|
||||
#[serde(rename = "adminTag")]
|
||||
pub admin_tag: Option<String>,
|
||||
#[serde(rename = "timeCreated")]
|
||||
|
@ -54,7 +54,7 @@ impl sqlx::Decode<'_, Postgres> for ThingPk {
|
||||
#[cfg(feature = "sqlx")]
|
||||
impl sqlx::Type<Postgres> for ThingPk {
|
||||
fn type_info() -> PgTypeInfo {
|
||||
PgTypeInfo::with_name("TEXT")
|
||||
PgTypeInfo::with_name("VARCHAR")
|
||||
}
|
||||
|
||||
fn compatible(ty: &<Postgres as sqlx::Database>::TypeInfo) -> bool {
|
||||
|
17
src/dto/filter.rs
Normal file
17
src/dto/filter.rs
Normal file
@ -0,0 +1,17 @@
|
||||
use serde::{Serialize, Deserialize};
|
||||
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Clone, Debug, PartialEq, PartialOrd)]
|
||||
pub enum Filter {
|
||||
Country(String),
|
||||
City(String),
|
||||
District(String),
|
||||
|
||||
PriceGreaterThan(f64),
|
||||
PriceLessThan(f64),
|
||||
|
||||
Rooms(i32),
|
||||
Bathrooms(i32),
|
||||
}
|
||||
|
@ -1 +1,2 @@
|
||||
pub mod payloads;
|
||||
pub mod filter;
|
@ -2,10 +2,8 @@ use chrono::{NaiveDate, Utc};
|
||||
use serde::{Deserialize, Serialize};
|
||||
use uuid::Uuid;
|
||||
|
||||
use crate::domain::{
|
||||
media::MediaList, project::Project, project_condition::ProjectCondition,
|
||||
project_state::ProjectState, project_type::ProjectType,
|
||||
};
|
||||
use crate::domain::{project_type::ProjectType, project_state::ProjectState, project_condition::ProjectCondition, media::MediaList, project::Project};
|
||||
|
||||
|
||||
#[derive(Serialize, Deserialize, Debug, Default, Clone, PartialEq, Eq, PartialOrd, Ord)]
|
||||
pub struct ProjectForCreationPayload {
|
||||
@ -32,6 +30,8 @@ pub struct ProjectForCreationPayload {
|
||||
#[serde(rename = "orderIndex")]
|
||||
pub order_index: i32,
|
||||
}
|
||||
|
||||
|
||||
impl From<ProjectForCreationPayload> for Project {
|
||||
fn from(value: ProjectForCreationPayload) -> Self {
|
||||
Self {
|
||||
@ -54,4 +54,4 @@ impl From<ProjectForCreationPayload> for Project {
|
||||
last_updated: Utc::now(),
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -4,7 +4,7 @@ use uuid::Uuid;
|
||||
|
||||
use crate::domain::{
|
||||
media::MediaList, property::Property, property_sale_type::PropertySaleType,
|
||||
property_type::PropertyType,
|
||||
property_type::PropertyType, format::FrameFormat,
|
||||
};
|
||||
|
||||
/// A property can belong to a project, or not. It should always belong to a realtor.
|
||||
@ -19,20 +19,22 @@ pub struct PropertyForCreationPayload {
|
||||
pub property_type: PropertyType,
|
||||
#[serde(rename = "propertySaleType")]
|
||||
pub property_sale_type: PropertySaleType,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub country: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub city: Option<String>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub district: Option<String>,
|
||||
#[serde(rename = "priceUsd")]
|
||||
pub price_usd: f64,
|
||||
pub country: String,
|
||||
pub city: String,
|
||||
pub district: String,
|
||||
/// This gives the realtor the option to order the projects/properties. On birth,
|
||||
#[serde(rename = "orderIndex")]
|
||||
pub order_index: i32,
|
||||
#[serde(rename = "thumbnailFormat")]
|
||||
pub thumbnail_format: FrameFormat,
|
||||
/// Amount of rooms in unit
|
||||
pub rooms: i16,
|
||||
/// Amount of bathrooms in unit
|
||||
pub bathrooms: f32,
|
||||
/// In meters squared
|
||||
pub area: f32,
|
||||
#[serde(rename = "parkingSpots")]
|
||||
pub parking_spots: i16,
|
||||
#[serde(rename = "adminTag")]
|
||||
pub admin_tag: Option<String>,
|
||||
}
|
||||
@ -49,10 +51,12 @@ impl From<PropertyForCreationPayload> for Property {
|
||||
country: value.country,
|
||||
city: value.city,
|
||||
district: value.district,
|
||||
price_usd: value.price_usd,
|
||||
order_index: value.order_index,
|
||||
thumbnail_format: value.thumbnail_format,
|
||||
rooms: value.rooms,
|
||||
bathrooms: value.bathrooms,
|
||||
area: value.area,
|
||||
parking_spots: value.parking_spots,
|
||||
admin_tag: value.admin_tag,
|
||||
time_created: Utc::now(),
|
||||
last_updated: Utc::now(),
|
||||
|
Loading…
Reference in New Issue
Block a user