Added get agent with id route

This commit is contained in:
Franklin 2023-04-25 08:47:48 -04:00
parent ca01d8d8ab
commit a9d6545322
8 changed files with 178 additions and 113 deletions

View File

@ -7,7 +7,8 @@ SELECT
(SELECT (SELECT u.price_usd FROM unit u WHERE u.project_id = p.id ORDER BY u.price_usd DESC LIMIT 1)) as starts_from, (SELECT (SELECT u.price_usd FROM unit u WHERE u.project_id = p.id ORDER BY u.price_usd DESC LIMIT 1)) as starts_from,
l.district, l.district,
p.finish_date, p.finish_date,
p.media as "media: _" p.media as "media: _",
p.admin_tag
FROM project p, location l FROM project p, location l
WHERE p.location_id = l.id WHERE p.location_id = l.id
-- Filters here: -- Filters here:

View File

@ -12,80 +12,6 @@
}, },
"query": "DELETE FROM agent WHERE id = $1;" "query": "DELETE FROM agent WHERE id = $1;"
}, },
"11b388533d1cece58959754172768a0fa4bfd430ad29a3bf0eca81bbbe7ecc22": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Uuid"
},
{
"name": "project_state: _",
"ordinal": 1,
"type_info": "Varchar"
},
{
"name": "project_type: _",
"ordinal": 2,
"type_info": "Varchar"
},
{
"name": "project_condition: _",
"ordinal": 3,
"type_info": "Varchar"
},
{
"name": "city",
"ordinal": 4,
"type_info": "Varchar"
},
{
"name": "starts_from",
"ordinal": 5,
"type_info": "Float8"
},
{
"name": "district",
"ordinal": 6,
"type_info": "Varchar"
},
{
"name": "finish_date",
"ordinal": 7,
"type_info": "Timestamp"
},
{
"name": "media: _",
"ordinal": 8,
"type_info": "Text"
}
],
"nullable": [
false,
false,
false,
false,
false,
null,
false,
false,
false
],
"parameters": {
"Left": [
"Text",
"Text",
"Text",
"Text",
"Text",
"Int2",
"Int8"
]
}
},
"query": "SELECT \n p.id,\n p.project_state as \"project_state: _\",\n p.project_type as \"project_type: _\",\n p.project_condition as \"project_condition: _\",\n l.city,\n (SELECT (SELECT u.price_usd FROM unit u WHERE u.project_id = p.id ORDER BY u.price_usd DESC LIMIT 1)) as starts_from,\n l.district,\n p.finish_date,\n p.media as \"media: _\"\nFROM project p, location l\nWHERE p.location_id = l.id\n-- Filters here:\nAND (LOWER(l.city) LIKE '%' || LOWER($1) || '%' OR $1 IS null) -- City Filter\nAND (LOWER(l.district) LIKE '%' || LOWER($2) || '%' OR $2 IS null) -- District Filter\nAND (p.project_type = $3 OR $3 IS null) -- ProjectType\nAND (p.project_condition = $4 OR $4 IS null) -- ProjectCondition\nAND (p.project_state = $5 OR $5 IS null) -- ProjectState\nAND ((SELECT COUNT(*) FROM unit u WHERE u.project_id = p.id AND u.rooms = $6) > 0 OR $6 IS NULL)\n-- End of filters\nORDER BY p.time_created DESC\nLIMIT 50 OFFSET $7;"
},
"19a20556f5e3621438cd583aae4984c8cf510f359f65ec599f8a6b46d9153ec4": { "19a20556f5e3621438cd583aae4984c8cf510f359f65ec599f8a6b46d9153ec4": {
"describe": { "describe": {
"columns": [ "columns": [
@ -620,6 +546,86 @@
}, },
"query": "INSERT INTO agent (\n id, shortcode, full_name, credential, credential_type, profile_picture_url, time_created, last_updated\n) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $7\n) RETURNING\nid,\nshortcode,\nfull_name,\ncredential,\ncredential_type as \"credential_type: _\",\nprofile_picture_url,\ntime_created,\nlast_updated;" "query": "INSERT INTO agent (\n id, shortcode, full_name, credential, credential_type, profile_picture_url, time_created, last_updated\n) VALUES (\n $1, $2, $3, $4, $5, $6, $7, $7\n) RETURNING\nid,\nshortcode,\nfull_name,\ncredential,\ncredential_type as \"credential_type: _\",\nprofile_picture_url,\ntime_created,\nlast_updated;"
}, },
"919dc414e70785bed4b999412b2ce5c46cb07e4aefb6a8c74bde23fcca9a4759": {
"describe": {
"columns": [
{
"name": "id",
"ordinal": 0,
"type_info": "Uuid"
},
{
"name": "project_state: _",
"ordinal": 1,
"type_info": "Varchar"
},
{
"name": "project_type: _",
"ordinal": 2,
"type_info": "Varchar"
},
{
"name": "project_condition: _",
"ordinal": 3,
"type_info": "Varchar"
},
{
"name": "city",
"ordinal": 4,
"type_info": "Varchar"
},
{
"name": "starts_from",
"ordinal": 5,
"type_info": "Float8"
},
{
"name": "district",
"ordinal": 6,
"type_info": "Varchar"
},
{
"name": "finish_date",
"ordinal": 7,
"type_info": "Timestamp"
},
{
"name": "media: _",
"ordinal": 8,
"type_info": "Text"
},
{
"name": "admin_tag",
"ordinal": 9,
"type_info": "Varchar"
}
],
"nullable": [
false,
false,
false,
false,
false,
null,
false,
false,
false,
true
],
"parameters": {
"Left": [
"Text",
"Text",
"Text",
"Text",
"Text",
"Int2",
"Int8"
]
}
},
"query": "SELECT \n p.id,\n p.project_state as \"project_state: _\",\n p.project_type as \"project_type: _\",\n p.project_condition as \"project_condition: _\",\n l.city,\n (SELECT (SELECT u.price_usd FROM unit u WHERE u.project_id = p.id ORDER BY u.price_usd DESC LIMIT 1)) as starts_from,\n l.district,\n p.finish_date,\n p.media as \"media: _\",\n p.admin_tag\nFROM project p, location l\nWHERE p.location_id = l.id\n-- Filters here:\nAND (LOWER(l.city) LIKE '%' || LOWER($1) || '%' OR $1 IS null) -- City Filter\nAND (LOWER(l.district) LIKE '%' || LOWER($2) || '%' OR $2 IS null) -- District Filter\nAND (p.project_type = $3 OR $3 IS null) -- ProjectType\nAND (p.project_condition = $4 OR $4 IS null) -- ProjectCondition\nAND (p.project_state = $5 OR $5 IS null) -- ProjectState\nAND ((SELECT COUNT(*) FROM unit u WHERE u.project_id = p.id AND u.rooms = $6) > 0 OR $6 IS NULL)\n-- End of filters\nORDER BY p.time_created DESC\nLIMIT 50 OFFSET $7;"
},
"924abcf88270de74ab6524fbd4247b2c23ab96b4569c8b81ff6b0e1d7dacada7": { "924abcf88270de74ab6524fbd4247b2c23ab96b4569c8b81ff6b0e1d7dacada7": {
"describe": { "describe": {
"columns": [ "columns": [

View File

@ -12,19 +12,19 @@ use jl_types::{
unit::Unit, unit::Unit,
}, },
dto::{ dto::{
item::Item,
payloads::{ payloads::{
agent::{NewAgentPayload, UpdateAgentPayload}, agent::{NewAgentPayload, UpdateAgentPayload},
location::NewLocationPayload, location::NewLocationPayload,
project::{NewProjectPayload, UpdateProjectPayload}, project::{NewProjectPayload, UpdateProjectPayload},
unit::{NewUnitPayload, UpdateUnitPayload}, unit::{NewUnitPayload, UpdateUnitPayload},
}, },
item::Item, },
}
}; };
use sqlx::PgPool; use sqlx::PgPool;
use uuid::Uuid; use uuid::Uuid;
use crate::{services}; use crate::services;
#[post("/agent")] #[post("/agent")]
pub async fn create_new_agent_profile( pub async fn create_new_agent_profile(
@ -129,7 +129,11 @@ pub async fn get_all_contacts(db_conn: web::Data<Arc<PgPool>>) -> TypedHttpRespo
services::admin::get_all_contacts(&db_conn).await services::admin::get_all_contacts(&db_conn).await
} }
#[post("images/{item}/{id}")] #[post("images/{item}")]
pub async fn upload_image(aws_client: web::Data<Arc<aws_sdk_s3::Client>>, path_vars: Path<(Item, Uuid)>, multipart: Multipart) -> TypedHttpResponse<String> { pub async fn upload_image(
services::admin::upload_image(&aws_client, path_vars.0.clone(), path_vars.1, multipart).await aws_client: web::Data<Arc<aws_sdk_s3::Client>>,
path_vars: Path<Item>,
multipart: Multipart,
) -> TypedHttpResponse<String> {
services::admin::upload_image(&aws_client, path_vars.clone(), multipart).await
} }

View File

@ -1,7 +1,10 @@
use std::sync::Arc; use std::sync::Arc;
use actix_cors::Cors; use actix_cors::Cors;
use actix_web::{web::{self}, App, HttpServer}; use actix_web::{
web::{self},
App, HttpServer,
};
use chrono::Utc; use chrono::Utc;
use reqwest::Client; use reqwest::Client;
use sqlx::PgPool; use sqlx::PgPool;
@ -38,7 +41,7 @@ pub async fn start_all_routes(start_time: i64, db_conn: Arc<PgPool>) -> Result<(
.service(super::admin::get_all_contacts) .service(super::admin::get_all_contacts)
.service(super::admin::get_contacts_count) .service(super::admin::get_contacts_count)
.service(super::admin::get_visits_count) .service(super::admin::get_visits_count)
.service(super::admin::upload_image) .service(super::admin::upload_image),
) )
.service( .service(
web::scope("/read") web::scope("/read")
@ -48,7 +51,9 @@ pub async fn start_all_routes(start_time: i64, db_conn: Arc<PgPool>) -> Result<(
.service(super::read::get_projects_paged) .service(super::read::get_projects_paged)
.service(super::read::get_project_data) .service(super::read::get_project_data)
.service(super::read::create_contact_request) .service(super::read::create_contact_request)
.service(super::read::get_agent_with_shortcode), .service(super::read::get_agent_with_shortcode)
.service(super::read::get_location_with_city_and_district)
.service(super::read::get_agent_with_id),
) )
}) })
.bind((HOST_ADDR, HOST_PORT))? .bind((HOST_ADDR, HOST_PORT))?

View File

@ -12,7 +12,10 @@ use actix_web::{
use actix_web_utils::extensions::typed_response::TypedHttpResponse; use actix_web_utils::extensions::typed_response::TypedHttpResponse;
use err::MessageResource; use err::MessageResource;
use jl_types::{ use jl_types::{
domain::{agent::Agent, project_condition::ProjectCondition, project_type::ProjectType}, domain::{
agent::Agent, location::Location, project_condition::ProjectCondition,
project_type::ProjectType,
},
dto::{ dto::{
filters::Filter, listing::Listing, payloads::contact::ContactPayload, filters::Filter, listing::Listing, payloads::contact::ContactPayload,
project_card::ProjectCardDto, project_card::ProjectCardDto,
@ -28,6 +31,11 @@ pub async fn get_all_agents(db_conn: web::Data<Arc<PgPool>>) -> TypedHttpRespons
services::read::get_all_agents(&db_conn).await services::read::get_all_agents(&db_conn).await
} }
#[get("/agent/{id}")]
pub async fn get_agent_with_id(db_conn: web::Data<Arc<PgPool>>, id: Path<Uuid>) -> TypedHttpResponse<Agent> {
services::read::get_agent_with_id(&db_conn, &id).await
}
#[get("/agent/{shortcode}")] #[get("/agent/{shortcode}")]
pub async fn get_agent_with_shortcode( pub async fn get_agent_with_shortcode(
db_conn: web::Data<Arc<PgPool>>, db_conn: web::Data<Arc<PgPool>>,
@ -50,7 +58,13 @@ pub async fn get_locations_in_city(
) -> TypedHttpResponse<HashSet<String>> { ) -> TypedHttpResponse<HashSet<String>> {
services::read::get_all_locations_in_city(&db_conn, &city).await services::read::get_all_locations_in_city(&db_conn, &city).await
} }
#[get("/location/{city}/{district}")]
pub async fn get_location_with_city_and_district(
db_conn: web::Data<Arc<PgPool>>,
path_vars: Path<(String, String)>,
) -> TypedHttpResponse<Location> {
services::read::get_location_with_city_and_district(&db_conn, &path_vars.0, &path_vars.1).await
}
#[get("/projects/{page}")] #[get("/projects/{page}")]
pub async fn get_projects_paged( pub async fn get_projects_paged(
request: HttpRequest, request: HttpRequest,

View File

@ -1,28 +1,30 @@
use actix_multipart::Multipart; use actix_multipart::Multipart;
use actix_web_utils::extensions::typed_response::TypedHttpResponse; use actix_web_utils::extensions::typed_response::TypedHttpResponse;
use err::MessageResource; use err::MessageResource;
use futures::StreamExt as _;
use jl_types::{ use jl_types::{
domain::{ domain::{
agent::Agent, contact::Contact, count::Count, location::Location, project::Project, agent::Agent, contact::Contact, count::Count, location::Location, project::Project,
unit::Unit, unit::Unit,
}, },
dto::{ dto::{
item::Item,
payloads::{ payloads::{
agent::{NewAgentPayload, UpdateAgentPayload}, agent::{NewAgentPayload, UpdateAgentPayload},
location::NewLocationPayload, location::NewLocationPayload,
project::{NewProjectPayload, UpdateProjectPayload}, project::{NewProjectPayload, UpdateProjectPayload},
unit::{NewUnitPayload, UpdateUnitPayload}, unit::{NewUnitPayload, UpdateUnitPayload},
}, },
item::Item, },
}
}; };
use futures::StreamExt as _;
use sqlx::PgPool; use sqlx::PgPool;
use uuid::Uuid; use uuid::Uuid;
use crate::{dao, handle_db_read_op, handle_db_write_op, handle_tx, success, unwrap_or_not_found, utils::s3::{self}}; use crate::{
dao, handle_db_read_op, handle_db_write_op, handle_tx, success, unwrap_or_not_found,
utils::s3::{self},
};
// //
// Insert Methods // Insert Methods
@ -203,20 +205,29 @@ pub async fn get_contact_count(conn: &PgPool) -> TypedHttpResponse<Count> {
success!(count) success!(count)
} }
pub async fn upload_image(client: &aws_sdk_s3::Client, item: Item, id: Uuid, mut multipart: Multipart) -> TypedHttpResponse<String> { pub async fn upload_image(
client: &aws_sdk_s3::Client,
item: Item,
mut multipart: Multipart,
) -> TypedHttpResponse<String> {
let mut bytes: Vec<u8> = Vec::new(); let mut bytes: Vec<u8> = Vec::new();
match multipart.next().await { match multipart.next().await {
Some(item) => { Some(item) => {
let mut field = match item { let mut field = match item {
Ok(field) => field, Ok(field) => field,
Err(error) => return TypedHttpResponse::return_standard_error(400, MessageResource::new_from_string(error.to_string())), Err(error) => {
return TypedHttpResponse::return_standard_error(
400,
MessageResource::new_from_string(error.to_string()),
)
}
}; };
// Field in turn is stream of *Bytes* object // Field in turn is stream of *Bytes* object
while let Some(chunk) = field.next().await { while let Some(chunk) = field.next().await {
bytes.append(&mut chunk.unwrap().to_vec()); bytes.append(&mut chunk.unwrap().to_vec());
} }
}, }
None => { None => {
return TypedHttpResponse::return_empty_response(400); return TypedHttpResponse::return_empty_response(400);
} }
@ -226,8 +237,13 @@ pub async fn upload_image(client: &aws_sdk_s3::Client, item: Item, id: Uuid, mut
return TypedHttpResponse::return_empty_response(400); return TypedHttpResponse::return_empty_response(400);
} }
match s3::upload_image(client, id, item, Uuid::new_v4().to_string(), bytes).await { match s3::upload_image(client, item, Uuid::new_v4().to_string(), bytes).await {
Ok(url) => success!(url), Ok(url) => success!(url),
Err(error) => return TypedHttpResponse::return_standard_error(400, MessageResource::new_from_string(error.to_string())), Err(error) => {
return TypedHttpResponse::return_standard_error(
400,
MessageResource::new_from_string(error.to_string()),
)
}
}; };
} }

View File

@ -2,7 +2,7 @@ use std::collections::HashSet;
use actix_web_utils::extensions::typed_response::TypedHttpResponse; use actix_web_utils::extensions::typed_response::TypedHttpResponse;
use jl_types::{ use jl_types::{
domain::agent::Agent, domain::{agent::Agent, location::Location},
dto::{ dto::{
filters::Filter, listing::Listing, payloads::contact::ContactPayload, filters::Filter, listing::Listing, payloads::contact::ContactPayload,
project_card::ProjectCardDto, project_card::ProjectCardDto,
@ -27,6 +27,16 @@ pub async fn get_agent_with_shortcode(
)) ))
} }
pub async fn get_agent_with_id(
conn: &PgPool,
id: &Uuid,
) -> TypedHttpResponse<Agent> {
success!(unwrap_or_not_found!(
handle_db_read_op!(dao::agent::get_agent_with_id(conn, id)),
"agents"
))
}
pub async fn get_all_locations(conn: &PgPool) -> TypedHttpResponse<HashSet<String>> { pub async fn get_all_locations(conn: &PgPool) -> TypedHttpResponse<HashSet<String>> {
let locations: HashSet<String> = handle_db_read_op!(dao::location::fetch_all_locations(conn)) let locations: HashSet<String> = handle_db_read_op!(dao::location::fetch_all_locations(conn))
.into_iter() .into_iter()
@ -47,7 +57,18 @@ pub async fn get_all_locations_in_city(
.collect() .collect()
) )
} }
pub async fn get_location_with_city_and_district(
conn: &PgPool,
city: &String,
district: &String,
) -> TypedHttpResponse<Location> {
success!(unwrap_or_not_found!(
handle_db_read_op!(dao::location::get_locations_in_city(conn, city))
.into_iter()
.find(|loc| &loc.district == district),
"locations"
))
}
pub async fn get_projects_paged( pub async fn get_projects_paged(
conn: &PgPool, conn: &PgPool,
page: &i64, page: &i64,

View File

@ -1,11 +1,7 @@
use jl_types::dto::item::Item;
use aws_sdk_s3::{ use aws_sdk_s3::{
error::SdkError, error::SdkError, operation::put_object::PutObjectError, primitives::ByteStream, Client,
operation::put_object::{PutObjectError},
primitives::ByteStream,
Client,
}; };
use uuid::Uuid; use jl_types::dto::item::Item;
pub async fn init_aws_client() -> Client { pub async fn init_aws_client() -> Client {
dotenv::dotenv().expect("Failed loading env"); dotenv::dotenv().expect("Failed loading env");
@ -15,12 +11,11 @@ pub async fn init_aws_client() -> Client {
pub async fn upload_image( pub async fn upload_image(
client: &Client, client: &Client,
id: Uuid,
item: Item, item: Item,
file_name: String, file_name: String,
multipart: Vec<u8>, multipart: Vec<u8>,
) -> Result<String, SdkError<PutObjectError>> { ) -> Result<String, SdkError<PutObjectError>> {
let path = format!("jl-images/{item}/{id}/{file_name}"); let path = format!("jl-images/{item}/{file_name}");
match client match client
.put_object() .put_object()
.bucket("jorge-ledesma-bucket") .bucket("jorge-ledesma-bucket")
@ -28,8 +23,11 @@ pub async fn upload_image(
.body(ByteStream::from(multipart)) .body(ByteStream::from(multipart))
.acl(aws_sdk_s3::types::ObjectCannedAcl::PublicRead) .acl(aws_sdk_s3::types::ObjectCannedAcl::PublicRead)
.send() .send()
.await { .await
Ok(_) => Ok(format!("https://jorge-ledesma-bucket.s3.us-east-2.amazonaws.com/{path}")), {
Ok(_) => Ok(format!(
"https://jorge-ledesma-bucket.s3.us-east-2.amazonaws.com/{path}"
)),
Err(error) => Err(error), Err(error) => Err(error),
} }
} }