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