Working on sql querys and daos

This commit is contained in:
Franklin 2023-03-09 13:45:16 -04:00
commit 866f8aca87
31 changed files with 2689 additions and 0 deletions

2
.env Normal file
View File

@ -0,0 +1,2 @@
DATABASE_URL="postgres://root:NMWrHZcu9QCu6wlmRUeEw1vXUYq7JhQYSPICTnl5yN9Pu5NIHUOcaj2noV9ejhFgfk5AfKIM2e9x97rbGCwbgTpVa3Fe8nfHgrYLZ2B36sOININQG60T2vIsQX3gkE6U@backend.blancoinfante.com:9102/postgres"
SQLX_OFFLINE=FALSE

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/target

2373
Cargo.lock generated Normal file

File diff suppressed because it is too large Load Diff

30
Cargo.toml Normal file
View File

@ -0,0 +1,30 @@
[package]
name = "remax-template"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
dotenvy = "0.15.6"
dotenvy_macro = "0.15.1"
tokio = {version = "1.20.1", features = ["full"]}
reqwest = { version = "0.11.11", features = ["rustls-tls", "json", "blocking"], default-features = false }
chrono = "0.4.23"
chrono-tz = "0.8"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0.88"
sqlx = { version = "0.6.0", features = [ "runtime-tokio-rustls", "postgres", "chrono", "uuid" ] }
dotenv = { version = "0.15.0" }
actix-web = {version = "4.1.0"}
actix-cors = "0.6.2"
uuid = { version = "1.3.0", features = ["v4", "fast-rng", "macro-diagnostics"] }
actix-web-utils = { git = "https://git.franklinblanco.dev/franklinblanco/actix-web-utils.git" }
err = { git = "https://git.franklinblanco.dev/franklinblanco/err.git" }
dev-dtos = { git = "https://git.franklinblanco.dev/franklinblanco/dev-dtos.git" }
dev-communicators = { git = "https://git.franklinblanco.dev/franklinblanco/dev-communicators.git" }
dev-macros = { git = "https://git.franklinblanco.dev/franklinblanco/dev-macros.git" }
remax-types = { path = "../remax-types" }

11
Readme.md Normal file
View File

@ -0,0 +1,11 @@
# Remax-template backend
by Franklin Blanco
### Todo's
- [ ] Add properties
- [ ] Add agents
- [ ] Fetch them both
- [ ] Delete, update
- [ ] Admin panel functions
- [ ] Pictures?

View File

@ -0,0 +1,9 @@
CREATE TABLE IF NOT EXISTS "property" (
id UUID PRIMARY KEY,
title VARCHAR NOT NULL,
description VARCHAR NOT NULL,
agent_id UUID NOT NULL,
state BYTEA NOT NULL,
time_created TIMESTAMPTZ NOT NULL,
last_updated TIMESTAMPTZ NOT NULL
);

6
migrations/2_agents.sql Normal file
View File

@ -0,0 +1,6 @@
CREATE TABLE IF NOT EXISTS "agent" (
id UUID PRIMARY KEY,
full_name VARCHAR NOT NULL,
time_created TIMESTAMPTZ NOT NULL,
last_updated TIMESTAMPTZ NOT NULL
);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS "property_details" (
property_id UUID PRIMARY KEY,
meters FLOAT4 NOT NULL,
listing_type BYTEA NOT NULL,
photo_urls BYTEA NOT NULL,
location_id UUID NOT NULL
);

View File

@ -0,0 +1,7 @@
CREATE TABLE IF NOT EXISTS "contact_info" (
agent_id UUID PRIMARY KEY,
phone_number VARCHAR NOT NULL,
email VARCHAR NOT NULL,
profile_picture_url TEXT,
default_message TEXT
);

View File

@ -0,0 +1,8 @@
CREATE TABLE IF NOT EXISTS "location" (
id UUID PRIMARY KEY,
country VARCHAR NOT NULL,
province VARCHAR NOT NULL,
city VARCHAR NOT NULL,
district VARCHAR,
google_maps_url TEXT
);

View File

@ -0,0 +1 @@
SELECT * FROM agent WHERE id = ANY($1);

5
sql/agent/insert.sql Normal file
View File

@ -0,0 +1,5 @@
INSERT INTO agent (
id, full_name, time_created, last_updated
) VALUES (
$1, $2, $3, $3
) RETURNING *

4
sql/agent/update.sql Normal file
View File

@ -0,0 +1,4 @@
UPDATE agent set
full_name = $1,
last_updated = $2
RETURNING *

View File

@ -0,0 +1 @@
SELECT * FROM contact_info where agent_id = ANY($1);

View File

@ -0,0 +1,5 @@
INSERT INTO contact_info (
agent_id, phone_number, email, profile_picture_url, default_message
) VALUES (
$1, $2, $3, $4, $5
) RETURNING *

View File

@ -0,0 +1,6 @@
UPDATE contact_info SET
phone_number = $1,
email = $2,
profile_picture_url = $3,
default_message = $4
RETURNING *

View File

@ -0,0 +1,9 @@
SELECT
id,
title,
description,
agent_id,
state as "state: _",
time_created,
last_updated
FROM property where id = ANY($1);

24
sql/property/insert.sql Normal file
View File

@ -0,0 +1,24 @@
INSERT INTO property (
id,
title,
description,
agent_id,
state,
time_created,
last_updated
) VALUES (
$1,
$2,
$3,
$4,
$5,
$6,
$6
) RETURNING
id,
title,
description,
agent_id,
state as "state: _",
time_created,
last_updated;

14
sql/property/update.sql Normal file
View File

@ -0,0 +1,14 @@
UPDATE property SET
title = $1,
description = $2,
agent_id = $3,
state = $4,
last_updated = $5
RETURNING
id,
title,
description,
agent_id,
state as "state: _",
time_created,
last_updated;

View File

@ -0,0 +1,7 @@
SELECT
property_id,
meters,
listing_type as "listing_type: _",
photo_urls as "photo_urls: _",
location_id
FROM property_details where property_id = ANY($1);

View File

@ -0,0 +1,18 @@
INSERT INTO property_details (
property_id,
meters,
listing_type,
photo_urls,
location_id,
) VALUES (
$1,
$2,
$3,
$4,
$5
) RETURNING
property_id,
meters,
listing_type as "listing_type: _",
photo_urls as "photo_urls: _",
location_id

View File

@ -0,0 +1,11 @@
UPDATE property_details SET
meters = $1,
listing_type = $2,
photo_urls = $3,
location_id = $4
RETURNING
property_id,
meters,
listing_type as "listing_type: _",
photo_urls as "photo_urls: _",
location_id

1
src/dao/agent.rs Normal file
View File

@ -0,0 +1 @@

10
src/dao/main_dao.rs Normal file
View File

@ -0,0 +1,10 @@
use dotenvy_macro::dotenv;
use sqlx::PgPool;
pub async fn connect_to_database() -> Result<PgPool, sqlx::Error> {
let db_url: &str = dotenv!("DATABASE_URL");
let formatted_db_url = &format!("{db_url}");
sqlx::PgPool::connect(&formatted_db_url).await
}

3
src/dao/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod agent;
pub mod main_dao;
pub mod property;

46
src/dao/property.rs Normal file
View File

@ -0,0 +1,46 @@
use remax_types::domain::property::Property;
use sqlx::PgPool;
use uuid::Uuid;
pub async fn insert_property(
conn: &PgPool,
property: &Property,
) -> Result<Property, sqlx::error::Error> {
sqlx::query_file_as!(
Property,
"sql/property/insert.sql",
property.id,
property.title,
property.description,
property.agent_id,
property.state as _,
property.time_created
)
.fetch_one(conn)
.await
}
pub async fn get_properties_with_ids(
conn: &PgPool,
ids: &Vec<Uuid>,
) -> Result<Vec<Property>, sqlx::error::Error> {
sqlx::query_file_as!(Property, "sql/property/fetch_with_ids.sql", ids)
.fetch_all(conn)
.await
}
pub async fn update_property(
conn: &PgPool,
property: &Property,
) -> Result<Property, sqlx::error::Error> {
sqlx::query_file_as!(
Property,
"sql/property/update.sql",
property.title,
property.description,
property.agent_id,
property.state as _,
property.last_updated
)
.fetch_one(conn)
.await
}

19
src/main.rs Normal file
View File

@ -0,0 +1,19 @@
pub mod dao;
pub mod routes;
use std::sync::Arc;
use chrono::Utc;
use dao::{main_dao};
#[tokio::main]
async fn main() {
let start_time = Utc::now().timestamp_millis();
let db_conn = Arc::new(main_dao::connect_to_database().await.unwrap());
// Pass shared state to server and start it
routes::main_router::start_all_routes(start_time, db_conn)
.await
.unwrap();
}

9
src/routes/admin.rs Normal file
View File

@ -0,0 +1,9 @@
// TODO: Property
// - Add property
// - Remove Properties by ids
// - Update Property
// TODO: Agent
// - Add agent
// - Remove agents
// - Update agents

3
src/routes/customer.rs Normal file
View File

@ -0,0 +1,3 @@
//TODO: Property
// - Get properties by novelty, by title, by size, by page, by cost, by contract_type
// - Properties should come with agents, property details, contact_info

36
src/routes/main_router.rs Normal file
View File

@ -0,0 +1,36 @@
use std::sync::Arc;
use actix_cors::Cors;
use actix_web::{web, App, HttpServer};
use chrono::Utc;
use reqwest::Client;
use sqlx::PgPool;
pub const HOST_ADDR: &str = "0.0.0.0";
pub const HOST_PORT: u16 = 8095;
pub async fn start_all_routes(start_time: i64, db_conn: Arc<PgPool>) -> Result<(), std::io::Error> {
let client_state = web::Data::new(Arc::new(Client::new()));
// Start server code that turns into a future to be executed below
let server_future = HttpServer::new(move || {
let cors_policy = Cors::permissive();
App::new()
.wrap(cors_policy)
.app_data(client_state.clone())
.app_data(db_conn.clone())
//.service(web::scope("/league").service(SERVICE_HERE))
})
.bind((HOST_ADDR, HOST_PORT))?
.run();
after_startup_fn(start_time);
server_future.await
}
pub fn after_startup_fn(start_time: i64) {
println!(
"Server took {}ms to setup",
Utc::now().timestamp_millis() - start_time
);
}

3
src/routes/mod.rs Normal file
View File

@ -0,0 +1,3 @@
pub mod admin;
pub mod customer;
pub mod main_router;