Working on sql querys and daos
This commit is contained in:
commit
866f8aca87
2
.env
Normal file
2
.env
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
DATABASE_URL="postgres://root:NMWrHZcu9QCu6wlmRUeEw1vXUYq7JhQYSPICTnl5yN9Pu5NIHUOcaj2noV9ejhFgfk5AfKIM2e9x97rbGCwbgTpVa3Fe8nfHgrYLZ2B36sOININQG60T2vIsQX3gkE6U@backend.blancoinfante.com:9102/postgres"
|
||||||
|
SQLX_OFFLINE=FALSE
|
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/target
|
2373
Cargo.lock
generated
Normal file
2373
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
30
Cargo.toml
Normal file
30
Cargo.toml
Normal 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
11
Readme.md
Normal 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?
|
9
migrations/1_property.sql
Normal file
9
migrations/1_property.sql
Normal 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
6
migrations/2_agents.sql
Normal 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
|
||||||
|
);
|
7
migrations/3_property_details.sql
Normal file
7
migrations/3_property_details.sql
Normal 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
|
||||||
|
);
|
7
migrations/4_contact_info.sql
Normal file
7
migrations/4_contact_info.sql
Normal 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
|
||||||
|
);
|
8
migrations/5_location.sql
Normal file
8
migrations/5_location.sql
Normal 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
|
||||||
|
);
|
1
sql/agent/fetch_with_ids.sql
Normal file
1
sql/agent/fetch_with_ids.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT * FROM agent WHERE id = ANY($1);
|
5
sql/agent/insert.sql
Normal file
5
sql/agent/insert.sql
Normal 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
4
sql/agent/update.sql
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
UPDATE agent set
|
||||||
|
full_name = $1,
|
||||||
|
last_updated = $2
|
||||||
|
RETURNING *
|
1
sql/contact_info/fetch_with_ids.sql
Normal file
1
sql/contact_info/fetch_with_ids.sql
Normal file
@ -0,0 +1 @@
|
|||||||
|
SELECT * FROM contact_info where agent_id = ANY($1);
|
5
sql/contact_info/insert.sql
Normal file
5
sql/contact_info/insert.sql
Normal 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 *
|
6
sql/contact_info/update.sql
Normal file
6
sql/contact_info/update.sql
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
UPDATE contact_info SET
|
||||||
|
phone_number = $1,
|
||||||
|
email = $2,
|
||||||
|
profile_picture_url = $3,
|
||||||
|
default_message = $4
|
||||||
|
RETURNING *
|
9
sql/property/fetch_with_ids.sql
Normal file
9
sql/property/fetch_with_ids.sql
Normal 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
24
sql/property/insert.sql
Normal 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
14
sql/property/update.sql
Normal 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;
|
7
sql/property_details/fetch_with_ids.sql
Normal file
7
sql/property_details/fetch_with_ids.sql
Normal 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);
|
18
sql/property_details/insert.sql
Normal file
18
sql/property_details/insert.sql
Normal 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
|
11
sql/property_details/update.sql
Normal file
11
sql/property_details/update.sql
Normal 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
1
src/dao/agent.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
|
10
src/dao/main_dao.rs
Normal file
10
src/dao/main_dao.rs
Normal 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
3
src/dao/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod agent;
|
||||||
|
pub mod main_dao;
|
||||||
|
pub mod property;
|
46
src/dao/property.rs
Normal file
46
src/dao/property.rs
Normal 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
19
src/main.rs
Normal 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
9
src/routes/admin.rs
Normal 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
3
src/routes/customer.rs
Normal 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
36
src/routes/main_router.rs
Normal 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
3
src/routes/mod.rs
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
pub mod admin;
|
||||||
|
pub mod customer;
|
||||||
|
pub mod main_router;
|
Loading…
Reference in New Issue
Block a user