Initial version
This commit is contained in:
12
src/connection.rs
Normal file
12
src/connection.rs
Normal file
@@ -0,0 +1,12 @@
|
||||
|
||||
use diesel::prelude::*;
|
||||
use dotenvy::dotenv;
|
||||
use std::env;
|
||||
|
||||
pub fn establish_connection() -> PgConnection {
|
||||
dotenv().ok();
|
||||
|
||||
let database_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
PgConnection::establish(&database_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", database_url))
|
||||
}
|
||||
1
src/constants.rs
Normal file
1
src/constants.rs
Normal file
@@ -0,0 +1 @@
|
||||
pub const APPLICATION_JSON: &str = "application/json";
|
||||
193
src/loota.rs
Normal file
193
src/loota.rs
Normal file
@@ -0,0 +1,193 @@
|
||||
use actix_web::{get, post, web, HttpResponse, Responder};
|
||||
use chrono::{NaiveDateTime};
|
||||
use diesel::prelude::*;
|
||||
use diesel::result::Error;
|
||||
use uuid::Uuid;
|
||||
use crate::constants::APPLICATION_JSON;
|
||||
use crate::connection::establish_connection;
|
||||
use crate::models::{Customer, Box, Order, LootaResponse, LootaBoxResponse, LootaRequest};
|
||||
use crate::schema::loota_box::dsl::loota_box;
|
||||
use crate::schema::loota_box::{delivery_date, id, pickup_date};
|
||||
use crate::schema::loota_customer::dsl::loota_customer;
|
||||
use crate::schema::loota_customer::identifier;
|
||||
|
||||
fn find_boxes(_identifier: String, _order: &Order, conn: &mut PgConnection) -> LootaResponse {
|
||||
let boxes = Box::belonging_to(_order)
|
||||
.select(Box::as_select())
|
||||
.order_by(delivery_date.asc())
|
||||
.load(conn);
|
||||
|
||||
match boxes {
|
||||
Ok(boxes) => {
|
||||
let _box_responses = boxes.iter().map(|b| {
|
||||
LootaBoxResponse {
|
||||
id: b.id.to_string(),
|
||||
delivery_date: b.delivery_date,
|
||||
pickup_date: b.pickup_date,
|
||||
}
|
||||
});
|
||||
|
||||
LootaResponse {
|
||||
identifier: _identifier.clone(),
|
||||
location: _order.location.clone(),
|
||||
boxes: _box_responses.collect(),
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
LootaResponse {
|
||||
identifier: "".to_string(),
|
||||
location: "".to_string(),
|
||||
boxes: vec![],
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn find_order(_customer: &Customer, conn: &mut PgConnection) -> Result<LootaResponse, Error> {
|
||||
let _identifier = _customer.identifier.clone();
|
||||
let order = Order::belonging_to(_customer)
|
||||
.select(Order::as_select())
|
||||
.limit(1)
|
||||
.load(conn);
|
||||
|
||||
match order {
|
||||
Ok(order) => match order.first() {
|
||||
Some(order) => Ok(find_boxes(_identifier, order, conn)),
|
||||
_ => Err(Error::NotFound)
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
fn find_customer(_identifier: String) -> Result<LootaResponse, Error> {
|
||||
let conn = &mut establish_connection();
|
||||
|
||||
let customer = loota_customer
|
||||
.filter(identifier.eq(_identifier))
|
||||
.select(Customer::as_select())
|
||||
.load(conn);
|
||||
|
||||
match customer {
|
||||
Ok(customer) => match customer.first() {
|
||||
Some(customer) => Ok(find_order(customer, conn)?),
|
||||
_ => Err(Error::NotFound)
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn update_box(_id: Uuid, _pickup_date: NaiveDateTime) -> Result<LootaBoxResponse, Error> {
|
||||
let conn = &mut establish_connection();
|
||||
|
||||
let loota = diesel::update(loota_box.filter(id.eq(&_id)))
|
||||
.set(pickup_date.eq(_pickup_date))
|
||||
.returning(Box::as_returning())
|
||||
.get_result(conn);
|
||||
|
||||
match loota {
|
||||
Ok(loota) => {
|
||||
Ok(LootaBoxResponse {
|
||||
id: loota.id.to_string(),
|
||||
delivery_date: loota.delivery_date,
|
||||
pickup_date: loota.pickup_date,
|
||||
})
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
Err(err)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
fn parse_uuid(_id: String) -> Result<Uuid, uuid::Error> {
|
||||
Uuid::parse_str(&_id)
|
||||
}
|
||||
|
||||
fn parse_date(_date: String) -> Result<NaiveDateTime, chrono::ParseError> {
|
||||
NaiveDateTime::parse_from_str(&_date, "%Y-%m-%dT%H:%M:%S")
|
||||
}
|
||||
|
||||
#[get("/loota/{id}")]
|
||||
async fn get(path: web::Path<String>) -> impl Responder {
|
||||
let identifer = path.into_inner();
|
||||
println!("id: {:?}", identifer);
|
||||
|
||||
let response = web::block(move || find_customer(identifer)).await.unwrap();
|
||||
|
||||
match response {
|
||||
Ok(response) => {
|
||||
HttpResponse::Ok()
|
||||
.content_type(APPLICATION_JSON).json(response)
|
||||
}
|
||||
_ => HttpResponse::NotFound()
|
||||
.content_type(APPLICATION_JSON)
|
||||
.await
|
||||
.unwrap(),
|
||||
}
|
||||
}
|
||||
|
||||
#[post("/loota/")]
|
||||
async fn update(req: web::Json<LootaRequest>) -> impl Responder {
|
||||
let box_id = parse_uuid(req.id.clone());
|
||||
|
||||
match box_id {
|
||||
Ok(box_id) => {
|
||||
|
||||
let date = parse_date(req.pickup_date.clone());
|
||||
match date {
|
||||
Ok(date) => {
|
||||
|
||||
let updated_box = update_box(box_id, date);
|
||||
match updated_box {
|
||||
Ok(updated_box) => {
|
||||
HttpResponse::Ok()
|
||||
.content_type(APPLICATION_JSON)
|
||||
.json(updated_box)
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
HttpResponse::BadRequest()
|
||||
.content_type(APPLICATION_JSON)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
HttpResponse::BadRequest()
|
||||
.content_type(APPLICATION_JSON)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Err(err) => {
|
||||
println!("Error: {:?}", err);
|
||||
HttpResponse::BadRequest()
|
||||
.content_type(APPLICATION_JSON)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
35
src/main.rs
Normal file
35
src/main.rs
Normal file
@@ -0,0 +1,35 @@
|
||||
extern crate actix_web;
|
||||
extern crate diesel;
|
||||
use std::{io};
|
||||
|
||||
|
||||
use actix_web::{middleware, App, HttpServer};
|
||||
use diesel::r2d2::{ConnectionManager, Pool, PooledConnection};
|
||||
use diesel::PgConnection;
|
||||
|
||||
mod constants;
|
||||
mod loota;
|
||||
mod models;
|
||||
mod schema;
|
||||
mod connection;
|
||||
|
||||
pub type DBPool = Pool<ConnectionManager<PgConnection>>;
|
||||
pub type DBPooledConnection = PooledConnection<ConnectionManager<PgConnection>>;
|
||||
|
||||
|
||||
#[actix_rt::main]
|
||||
async fn main() -> io::Result<()> {
|
||||
env_logger::init();
|
||||
|
||||
HttpServer::new(|| {
|
||||
App::new()
|
||||
// enable logger - always register actix-web Logger middleware last
|
||||
.wrap(middleware::Logger::default())
|
||||
// register HTTP requests handlers
|
||||
.service(loota::get)
|
||||
.service(loota::update)
|
||||
})
|
||||
.bind("0.0.0.0:9090")?
|
||||
.run()
|
||||
.await
|
||||
}
|
||||
55
src/models.rs
Normal file
55
src/models.rs
Normal file
@@ -0,0 +1,55 @@
|
||||
use uuid::Uuid;
|
||||
use diesel::prelude::*;
|
||||
use chrono::{NaiveDateTime};
|
||||
use serde::{Serialize, Deserialize};
|
||||
use crate::schema::{loota_customer, loota_order, loota_box};
|
||||
|
||||
|
||||
#[derive(Queryable, Identifiable, Selectable, Debug, PartialEq)]
|
||||
#[diesel(table_name = loota_customer)]
|
||||
pub struct Customer {
|
||||
pub id: Uuid,
|
||||
pub identifier: String
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Identifiable, Associations, Debug, PartialEq)]
|
||||
#[diesel(belongs_to(Customer))]
|
||||
#[diesel(table_name = loota_order)]
|
||||
pub struct Order {
|
||||
pub id: Uuid,
|
||||
pub location: String,
|
||||
pub customer_id: Uuid,
|
||||
}
|
||||
|
||||
#[derive(Queryable, Selectable, Identifiable, Associations, Debug, PartialEq)]
|
||||
#[diesel(belongs_to(Order))]
|
||||
#[diesel(table_name = loota_box)]
|
||||
#[diesel(check_for_backend(diesel::pg::Pg))]
|
||||
pub struct Box {
|
||||
pub id: Uuid,
|
||||
pub delivery_date: Option<NaiveDateTime>,
|
||||
pub pickup_date: Option<NaiveDateTime>,
|
||||
pub order_id: Uuid
|
||||
}
|
||||
|
||||
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct LootaResponse {
|
||||
pub identifier: String,
|
||||
pub location: String,
|
||||
pub boxes: Vec<LootaBoxResponse>
|
||||
}
|
||||
|
||||
#[derive(Debug, Serialize)]
|
||||
pub struct LootaBoxResponse {
|
||||
pub id: String,
|
||||
pub delivery_date: Option<NaiveDateTime>,
|
||||
pub pickup_date: Option<NaiveDateTime>
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize)]
|
||||
pub struct LootaRequest {
|
||||
pub id: String,
|
||||
pub pickup_date: String
|
||||
}
|
||||
37
src/schema.rs
Normal file
37
src/schema.rs
Normal file
@@ -0,0 +1,37 @@
|
||||
// @generated automatically by Diesel CLI.
|
||||
|
||||
diesel::table! {
|
||||
loota_box (id) {
|
||||
id -> Uuid,
|
||||
order_id -> Uuid,
|
||||
delivery_date -> Nullable<Timestamp>,
|
||||
pickup_date -> Nullable<Timestamp>,
|
||||
created_time -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
loota_customer (id) {
|
||||
id -> Uuid,
|
||||
identifier -> Varchar,
|
||||
created_time -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::table! {
|
||||
loota_order (id) {
|
||||
id -> Uuid,
|
||||
customer_id -> Uuid,
|
||||
location -> Varchar,
|
||||
created_time -> Timestamp,
|
||||
}
|
||||
}
|
||||
|
||||
diesel::joinable!(loota_box -> loota_order (order_id));
|
||||
diesel::joinable!(loota_order -> loota_customer (customer_id));
|
||||
|
||||
diesel::allow_tables_to_appear_in_same_query!(
|
||||
loota_box,
|
||||
loota_customer,
|
||||
loota_order,
|
||||
);
|
||||
Reference in New Issue
Block a user