Initial commit
This commit is contained in:
commit
3fc73fa6ac
11
.gitignore
vendored
Normal file
11
.gitignore
vendored
Normal file
@ -0,0 +1,11 @@
|
||||
/target
|
||||
/Cargo.lock
|
||||
|
||||
*~
|
||||
\#*\#
|
||||
/.emacs.desktop
|
||||
/.emacs.desktop.lock
|
||||
*.elc
|
||||
auto-save-list
|
||||
tramp
|
||||
.\#*
|
||||
17
Cargo.toml
Normal file
17
Cargo.toml
Normal file
@ -0,0 +1,17 @@
|
||||
[package]
|
||||
name = "pos"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[dependencies]
|
||||
tide = "0.16.0"
|
||||
async-std = { version = "1.12.0", features = ["attributes"] }
|
||||
sqlx = { version = "0.6.2", features = ["runtime-async-std-native-tls", "chrono", "json", "sqlite"] }
|
||||
dotenv = "0.15.0"
|
||||
chrono = "0.4"
|
||||
serde_json = "1.0"
|
||||
anyhow = "1.0.65"
|
||||
serde = { version = "1.0.145", features = ["derive"] }
|
||||
pretty_env_logger = "0.4.0"
|
||||
5
migrations/down.sql
Normal file
5
migrations/down.sql
Normal file
@ -0,0 +1,5 @@
|
||||
-- This file should undo anything in `up.sql`
|
||||
DROP TABLE products;
|
||||
DROP TABLE orders_products;
|
||||
DROP TABLE orders;
|
||||
DROP VIEW totals_per_owner_and_order;
|
||||
56
migrations/up.sql
Normal file
56
migrations/up.sql
Normal file
@ -0,0 +1,56 @@
|
||||
-- Your SQL goes here
|
||||
CREATE TABLE products (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
name TEXT UNIQUE NOT NULL,
|
||||
price REAL NOT NULL,
|
||||
owner TEXT NOT NULL,
|
||||
created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE orders (
|
||||
id INTEGER PRIMARY KEY NOT NULL,
|
||||
created_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP NOT NULL
|
||||
);
|
||||
|
||||
CREATE TABLE orders_products (
|
||||
order_id INTEGER NOT NULL,
|
||||
product_id INTEGER NOT NULL,
|
||||
quantity INTEGER NOT NULL,
|
||||
FOREIGN KEY (order_id) REFERENCES orders(id),
|
||||
FOREIGN KEY (product_id) REFERENCES products(id),
|
||||
PRIMARY KEY (order_id, product_id)
|
||||
);
|
||||
|
||||
INSERT INTO products (name, price, owner)
|
||||
VALUES
|
||||
("Pfadiburger", 5.1, "Pfadfinder"),
|
||||
("Kuchen", 2, "Sportunion"),
|
||||
("Apfelsaft", 1.5, "Sportunion"),
|
||||
("Käsekrainer", 4, "Pfadfinder"),
|
||||
("Süßes", 0.2, "Pfadfinder"),
|
||||
("Capuccino", 3.5, "Deluke"),
|
||||
("Espresso", 2.5, "Deluke");
|
||||
|
||||
INSERT INTO orders DEFAULT VALUES;
|
||||
INSERT INTO orders_products (order_id, product_id, quantity)
|
||||
VALUES
|
||||
(1, 1, 3),
|
||||
(1, 2, 1),
|
||||
(1, 5, 1);
|
||||
|
||||
INSERT INTO orders DEFAULT VALUES;
|
||||
INSERT INTO orders_products (order_id, product_id, quantity)
|
||||
VALUES
|
||||
(2, 4, 2),
|
||||
(2, 6, 2),
|
||||
(2, 2, 1);
|
||||
|
||||
CREATE VIEW totals_per_owner_and_order AS
|
||||
SELECT id, owner, SUM(total_price) AS total FROM (
|
||||
SELECT o.id, p.owner, p.price*op.quantity AS total_price FROM orders AS o
|
||||
INNER JOIN orders_products AS op ON o.id = op.order_id
|
||||
INNER JOIN products AS p ON p.id = op.product_id
|
||||
)
|
||||
GROUP BY id, owner;
|
||||
61
src/db.rs
Normal file
61
src/db.rs
Normal file
@ -0,0 +1,61 @@
|
||||
pub mod models;
|
||||
pub mod schema;
|
||||
|
||||
use anyhow::Result;
|
||||
use diesel::prelude::*;
|
||||
use dotenv::dotenv;
|
||||
use std::env;
|
||||
|
||||
use self::{models::*, schema::*};
|
||||
|
||||
pub fn establish_connection() -> SqliteConnection {
|
||||
dotenv().ok();
|
||||
|
||||
let db_url = env::var("DATABASE_URL").expect("DATABASE_URL must be set");
|
||||
SqliteConnection::establish(&db_url)
|
||||
.unwrap_or_else(|_| panic!("Error connecting to {}", db_url))
|
||||
}
|
||||
|
||||
pub fn get_products() -> Vec<Product> {
|
||||
use self::schema::products::dsl::*;
|
||||
let conn = &mut establish_connection();
|
||||
products
|
||||
.load::<Product>(conn)
|
||||
.expect("Error loading products")
|
||||
}
|
||||
|
||||
pub fn get_products_from_order(order: &Order, conn: &mut SqliteConnection) -> Vec<Product> {
|
||||
let res: Vec<(OrderProduct, Product)> = OrderProduct::belonging_to(order)
|
||||
.inner_join(products::table)
|
||||
.get_results(conn);
|
||||
// Strip off all the elements from the linking table
|
||||
res.into_iter().map(|(_ri, i)| i).collect()
|
||||
}
|
||||
|
||||
pub fn create_product(
|
||||
conn: &mut SqliteConnection,
|
||||
name: &str,
|
||||
price: &f32,
|
||||
owner: &str,
|
||||
) -> Product {
|
||||
let new_product = NewProduct { name, price, owner };
|
||||
|
||||
diesel::insert_into(products::table)
|
||||
.values(&new_product)
|
||||
.get_result(conn)
|
||||
.expect("Error saving new product")
|
||||
}
|
||||
|
||||
pub fn create_order(
|
||||
conn: &mut SqliteConnection,
|
||||
products: Vec<Product>,
|
||||
) -> Result<(Order, Vec<Product>)> {
|
||||
let order = diesel::insert_into(orders::table)
|
||||
.default_values()
|
||||
.get_result(conn)?;
|
||||
|
||||
for product in products {
|
||||
let product_exists = diesel::select(diesel::dsl::exists(products.filter(name.eq(product.name))))
|
||||
.get_result(conn);
|
||||
}
|
||||
}
|
||||
43
src/main.rs
Normal file
43
src/main.rs
Normal file
@ -0,0 +1,43 @@
|
||||
use serde::{Deserialize, Serialize};
|
||||
use dotenv;
|
||||
use sqlx::{sqlite::SqlitePoolOptions, SqlitePool};
|
||||
use tide::{Body, Request, Result};
|
||||
|
||||
#[derive(Deserialize, Serialize)]
|
||||
struct Product {
|
||||
name: String,
|
||||
}
|
||||
|
||||
#[async_std::main]
|
||||
async fn main() -> Result<()> {
|
||||
dotenv::dotenv().ok();
|
||||
pretty_env_logger::init();
|
||||
|
||||
let db_pool = make_db_pool().await;
|
||||
let mut app = tide::new();
|
||||
app.at("/products").post(create_product);
|
||||
app.listen("127.0.0.1:8080").await?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn make_db_pool() -> SqlitePool {
|
||||
let db_url =
|
||||
std::env::var("DATABASE_URL").expect("Environment variable DATABASE_URL must be set");
|
||||
let db_pool = SqlitePoolOptions::new()
|
||||
.max_connections(2)
|
||||
.connect(&format!("sqlite://{}?mode=rwc", &db_url))
|
||||
.await
|
||||
.expect("Could not connect to database");
|
||||
db_pool
|
||||
}
|
||||
|
||||
async fn create_product(mut req: Request<()>) -> Result<Body> {
|
||||
let product: Product = req.body_json().await?;
|
||||
println!("product name: {}", product.name);
|
||||
|
||||
let product = Product {
|
||||
name: "chashu".into(),
|
||||
};
|
||||
|
||||
Body::from_json(&product)
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user