Init
This commit is contained in:
commit
5bef67cc1e
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
||||
/target
|
4024
Cargo.lock
generated
Normal file
4024
Cargo.lock
generated
Normal file
File diff suppressed because it is too large
Load Diff
2
Cargo.toml
Normal file
2
Cargo.toml
Normal file
@ -0,0 +1,2 @@
|
||||
[workspace]
|
||||
members = ["web"]
|
5
README.md
Normal file
5
README.md
Normal file
@ -0,0 +1,5 @@
|
||||
# Bazzar
|
||||
|
||||
### Order life cycle
|
||||
|
||||
<img src="./assets/order-lifecycle.svg" alt="order lifecycle">
|
13
assets/order-flow.dot
Normal file
13
assets/order-flow.dot
Normal file
@ -0,0 +1,13 @@
|
||||
digraph OrderLifecycle {
|
||||
Confirmed -> Payed;
|
||||
Confirmed -> Delivered;
|
||||
Confirmed -> Cancelled;
|
||||
Payed -> Delivered;
|
||||
Payed -> RequireRefund;
|
||||
RequireRefund -> Refunded;
|
||||
|
||||
Confirmed [shape=diamond];
|
||||
Delivered [shape=box];
|
||||
Cancelled [shape=box];
|
||||
Refunded [shape = box];
|
||||
}
|
107
assets/order-lifecycle.svg
Normal file
107
assets/order-lifecycle.svg
Normal file
@ -0,0 +1,107 @@
|
||||
<svg width="238pt" height="260pt"
|
||||
viewBox="0.00 0.00 237.63 260.00" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g id="graph0" class="graph" transform="scale(1 1) rotate(0) translate(4 256)">
|
||||
<title>OrderLifecycle</title>
|
||||
<polygon fill="#ffffff" stroke="transparent" points="-4,4 -4,-256 233.6288,-256 233.6288,4 -4,4"/>
|
||||
<!-- Confirmed -->
|
||||
<g id="node1" class="node">
|
||||
<title>Confirmed</title>
|
||||
<polygon fill="none" stroke="#000000"
|
||||
points="98.5961,-252 24.0445,-234 98.5961,-216 173.1477,-234 98.5961,-252"/>
|
||||
<text text-anchor="middle" x="98.5961" y="-229.8" font-family="Times,serif" font-size="14.00"
|
||||
fill="#000000">Confirmed
|
||||
</text>
|
||||
</g>
|
||||
<!-- Payed -->
|
||||
<g id="node2" class="node">
|
||||
<title>Payed</title>
|
||||
<ellipse fill="none" stroke="#000000" cx="98.5961" cy="-162" rx="34.7709" ry="18"/>
|
||||
<text text-anchor="middle" x="98.5961" y="-157.8" font-family="Times,serif" font-size="14.00"
|
||||
fill="#000000">Payed
|
||||
</text>
|
||||
</g>
|
||||
<!-- Confirmed->Payed -->
|
||||
<g id="edge1" class="edge">
|
||||
<title>Confirmed->Payed</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M98.5961,-215.8314C98.5961,-208.131 98.5961,-198.9743 98.5961,-190.4166"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="102.0962,-190.4132 98.5961,-180.4133 95.0962,-190.4133 102.0962,-190.4132"/>
|
||||
</g>
|
||||
<!-- Delivered -->
|
||||
<g id="node3" class="node">
|
||||
<title>Delivered</title>
|
||||
<polygon fill="none" stroke="#000000"
|
||||
points="71.2886,-108 -.0964,-108 -.0964,-72 71.2886,-72 71.2886,-108"/>
|
||||
<text text-anchor="middle" x="35.5961" y="-85.8" font-family="Times,serif" font-size="14.00" fill="#000000">
|
||||
Delivered
|
||||
</text>
|
||||
</g>
|
||||
<!-- Confirmed->Delivered -->
|
||||
<g id="edge2" class="edge">
|
||||
<title>Confirmed->Delivered</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M83.3313,-219.3093C73.6635,-209.1515 61.6888,-194.8386 54.5961,-180 45.2698,-160.4883 40.4937,-136.4348 38.0637,-118.1046"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="41.5258,-117.5765 36.8873,-108.051 34.5733,-118.39 41.5258,-117.5765"/>
|
||||
</g>
|
||||
<!-- Cancelled -->
|
||||
<g id="node4" class="node">
|
||||
<title>Cancelled</title>
|
||||
<polygon fill="none" stroke="#000000"
|
||||
points="223.5723,-180 151.6199,-180 151.6199,-144 223.5723,-144 223.5723,-180"/>
|
||||
<text text-anchor="middle" x="187.5961" y="-157.8" font-family="Times,serif" font-size="14.00"
|
||||
fill="#000000">Cancelled
|
||||
</text>
|
||||
</g>
|
||||
<!-- Confirmed->Cancelled -->
|
||||
<g id="edge3" class="edge">
|
||||
<title>Confirmed->Cancelled</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M115.7562,-220.1177C127.4948,-210.6213 143.3774,-197.7724 157.2239,-186.5707"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="159.5213,-189.2141 165.0945,-180.2035 155.1187,-183.772 159.5213,-189.2141"/>
|
||||
</g>
|
||||
<!-- Payed->Delivered -->
|
||||
<g id="edge4" class="edge">
|
||||
<title>Payed->Delivered</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M83.9843,-145.3008C76.2975,-136.5159 66.7059,-125.5541 58.0942,-115.7121"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="60.6721,-113.3432 51.453,-108.1222 55.404,-117.9527 60.6721,-113.3432"/>
|
||||
</g>
|
||||
<!-- RequireRefund -->
|
||||
<g id="node5" class="node">
|
||||
<title>RequireRefund</title>
|
||||
<ellipse fill="none" stroke="#000000" cx="159.5961" cy="-90" rx="70.0654" ry="18"/>
|
||||
<text text-anchor="middle" x="159.5961" y="-85.8" font-family="Times,serif" font-size="14.00"
|
||||
fill="#000000">RequireRefund
|
||||
</text>
|
||||
</g>
|
||||
<!-- Payed->RequireRefund -->
|
||||
<g id="edge5" class="edge">
|
||||
<title>Payed->RequireRefund</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M112.744,-145.3008C120.2979,-136.3848 129.7515,-125.2264 138.1849,-115.2722"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="140.8801,-117.5055 144.6738,-107.6132 135.5392,-112.9806 140.8801,-117.5055"/>
|
||||
</g>
|
||||
<!-- Refunded -->
|
||||
<g id="node6" class="node">
|
||||
<title>Refunded</title>
|
||||
<polygon fill="none" stroke="#000000"
|
||||
points="195.0238,-36 124.1684,-36 124.1684,0 195.0238,0 195.0238,-36"/>
|
||||
<text text-anchor="middle" x="159.5961" y="-13.8" font-family="Times,serif" font-size="14.00"
|
||||
fill="#000000">Refunded
|
||||
</text>
|
||||
</g>
|
||||
<!-- RequireRefund->Refunded -->
|
||||
<g id="edge6" class="edge">
|
||||
<title>RequireRefund->Refunded</title>
|
||||
<path fill="none" stroke="#000000"
|
||||
d="M159.5961,-71.8314C159.5961,-64.131 159.5961,-54.9743 159.5961,-46.4166"/>
|
||||
<polygon fill="#000000" stroke="#000000"
|
||||
points="163.0962,-46.4132 159.5961,-36.4133 156.0962,-46.4133 163.0962,-46.4132"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
After Width: | Height: | Size: 5.5 KiB |
69
db/migrate/202204131841_init.sql
Normal file
69
db/migrate/202204131841_init.sql
Normal file
@ -0,0 +1,69 @@
|
||||
CREATE EXTENSION "uuid-ossp";
|
||||
|
||||
CREATE TYPE "Role" AS ENUM (
|
||||
'Admin',
|
||||
'User'
|
||||
);
|
||||
|
||||
CREATE TYPE "OrderStatus" AS ENUM (
|
||||
'Confirmed',
|
||||
'Cancelled',
|
||||
'Delivered',
|
||||
'Payed',
|
||||
'RequireRefund',
|
||||
'Refunded'
|
||||
);
|
||||
|
||||
CREATE TABLE accounts
|
||||
(
|
||||
id serial not null primary key,
|
||||
email varchar not null unique,
|
||||
login varchar not null unique,
|
||||
pass_hash varchar not null,
|
||||
role "Role" not null default 'User'
|
||||
);
|
||||
|
||||
CREATE TABLE products
|
||||
(
|
||||
id serial not null primary key,
|
||||
name varchar not null unique,
|
||||
short_description varchar not null,
|
||||
long_description varchar not null,
|
||||
category varchar,
|
||||
price_major int not null,
|
||||
price_minor int not null,
|
||||
CONSTRAINT positive_price_minor check ( price_major >= 0 )
|
||||
);
|
||||
|
||||
CREATE TABLE stocks
|
||||
(
|
||||
id serial not null primary key,
|
||||
product_id int references products (id) not null unique,
|
||||
quantity int not null default 0,
|
||||
CONSTRAINT positive_quantity check ( quantity >= 0 )
|
||||
);
|
||||
|
||||
CREATE TABLE account_orders
|
||||
(
|
||||
id serial not null primary key,
|
||||
buyer_id int references accounts (id) not null,
|
||||
status "OrderStatus" not null default 'Confirmed'
|
||||
);
|
||||
|
||||
CREATE TABLE order_items
|
||||
(
|
||||
id serial not null primary key,
|
||||
product_id int references products (id) not null,
|
||||
order_id int references account_orders (id),
|
||||
quantity int not null default 0,
|
||||
CONSTRAINT positive_quantity check ( quantity >= 0 )
|
||||
);
|
||||
|
||||
CREATE TABLE statistics
|
||||
(
|
||||
id serial not null primary key,
|
||||
url varchar not null,
|
||||
clicks int not null default 0,
|
||||
date DATE not null default now(),
|
||||
CONSTRAINT positive_clicks check ( clicks >= 0 )
|
||||
);
|
7
web/Cargo.lock
generated
Normal file
7
web/Cargo.lock
generated
Normal file
@ -0,0 +1,7 @@
|
||||
# This file is automatically @generated by Cargo.
|
||||
# It is not intended for manual editing.
|
||||
version = 3
|
||||
|
||||
[[package]]
|
||||
name = "web"
|
||||
version = "0.1.0"
|
39
web/Cargo.toml
Normal file
39
web/Cargo.toml
Normal file
@ -0,0 +1,39 @@
|
||||
[package]
|
||||
name = "bazzar"
|
||||
version = "0.1.0"
|
||||
edition = "2021"
|
||||
|
||||
[dependencies]
|
||||
actix = { version = "0.13.0" }
|
||||
actix-rt = { version = "2.7.0" }
|
||||
actix-web = { version = "4.0.1" }
|
||||
actix-auth = { version = "0.1.0" }
|
||||
actix-cors = { version = "0.6.1" }
|
||||
actix-files = { version = "0.6.0" }
|
||||
actix-multipart = { version = "0.4.0" }
|
||||
actix-broker = { version = "0.4.2" }
|
||||
actix-identity = { version = "0.4.0" }
|
||||
actix-web-opentelemetry = { version = "0.12.0" }
|
||||
|
||||
tera = { version = "1.15.0" }
|
||||
|
||||
tracing = { version = "0.1.33" }
|
||||
|
||||
uuid = { version = "0.8.2", features = ["serde"] }
|
||||
chrono = { version = "*", features = ["serde"] }
|
||||
|
||||
serde = { version = "1.0.136", features = ["derive"] }
|
||||
serde_json = { version = "1.0.79" }
|
||||
toml = { version = "0.5.8" }
|
||||
|
||||
sqlx = { version = "0.5.11", features = ["migrate", "runtime-actix-rustls", "all-types", "postgres"] }
|
||||
|
||||
log = { version = "0.4.16" }
|
||||
pretty_env_logger = { version = "0.4.0" }
|
||||
|
||||
dotenv = { version = "0.15.0" }
|
||||
|
||||
derive_more = { version = "0.99.17" }
|
||||
parking_lot = { version = "0.12.0" }
|
||||
|
||||
password-hash = { version = "0.4.0" }
|
0
web/src/actors/database.rs
Normal file
0
web/src/actors/database.rs
Normal file
1
web/src/actors/mod.rs
Normal file
1
web/src/actors/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
pub mod database;
|
1
web/src/logic/mod.rs
Normal file
1
web/src/logic/mod.rs
Normal file
@ -0,0 +1 @@
|
||||
mod order_state;
|
21
web/src/logic/order_state.rs
Normal file
21
web/src/logic/order_state.rs
Normal file
@ -0,0 +1,21 @@
|
||||
use crate::model::OrderStatus;
|
||||
|
||||
pub fn change(current: OrderStatus, next: OrderStatus) -> Option<OrderStatus> {
|
||||
match (current, next) {
|
||||
// paying
|
||||
(OrderStatus::Confirmed, OrderStatus::Payed) => Some(OrderStatus::Payed),
|
||||
|
||||
// delivering
|
||||
(OrderStatus::Confirmed | OrderStatus::Payed, OrderStatus::Delivered) => {
|
||||
Some(OrderStatus::Delivered)
|
||||
}
|
||||
|
||||
// cancelling
|
||||
(OrderStatus::Confirmed, OrderStatus::Cancelled) => Some(OrderStatus::Cancelled),
|
||||
(OrderStatus::Payed, OrderStatus::Cancelled) => Some(OrderStatus::RequireRefund),
|
||||
(OrderStatus::Payed, OrderStatus::RequireRefund) => Some(OrderStatus::RequireRefund),
|
||||
(OrderStatus::RequireRefund, OrderStatus::Refunded) => Some(OrderStatus::Refunded),
|
||||
|
||||
_ => None,
|
||||
}
|
||||
}
|
14
web/src/main.rs
Normal file
14
web/src/main.rs
Normal file
@ -0,0 +1,14 @@
|
||||
mod actors;
|
||||
mod logic;
|
||||
mod model;
|
||||
mod routes;
|
||||
|
||||
use actix_web::{App, HttpServer};
|
||||
|
||||
#[actix_web::main] // or #[tokio::main]
|
||||
async fn main() -> std::io::Result<()> {
|
||||
HttpServer::new(|| App::new().configure(routes::configure))
|
||||
.bind(("127.0.0.1", 8080))?
|
||||
.run()
|
||||
.await
|
||||
}
|
25
web/src/model.rs
Normal file
25
web/src/model.rs
Normal file
@ -0,0 +1,25 @@
|
||||
use derive_more::Display;
|
||||
|
||||
#[derive(sqlx::Type, Copy, Clone, Debug, Display)]
|
||||
pub enum OrderStatus {
|
||||
#[display(fmt = "Potwierdzone")]
|
||||
Confirmed,
|
||||
#[display(fmt = "Odebrane")]
|
||||
Delivered,
|
||||
#[display(fmt = "Opłacone")]
|
||||
Payed,
|
||||
#[display(fmt = "Anulowane")]
|
||||
Cancelled,
|
||||
#[display(fmt = "Wymaga zwrotu płatności")]
|
||||
RequireRefund,
|
||||
#[display(fmt = "Płatność zwrócona")]
|
||||
Refunded,
|
||||
}
|
||||
|
||||
#[derive(sqlx::Type, Copy, Clone, Debug, Display)]
|
||||
pub enum Role {
|
||||
#[display(fmt = "Adminitrator")]
|
||||
Admin,
|
||||
#[display(fmt = "Użytkownik")]
|
||||
User,
|
||||
}
|
23
web/src/routes/admin.rs
Normal file
23
web/src/routes/admin.rs
Normal file
@ -0,0 +1,23 @@
|
||||
// use actix_auth::login_required;
|
||||
use actix_identity::Identity;
|
||||
use actix_web::web::ServiceConfig;
|
||||
use actix_web::{delete, get, post, HttpResponse};
|
||||
|
||||
#[delete("/admin/logout")]
|
||||
async fn logout() -> HttpResponse {
|
||||
HttpResponse::NotImplemented().body("")
|
||||
}
|
||||
|
||||
#[post("/admin/sign-in")]
|
||||
async fn sign_in(_id: Identity) -> HttpResponse {
|
||||
HttpResponse::NotImplemented().body("")
|
||||
}
|
||||
|
||||
#[get("/admin")]
|
||||
async fn landing() -> HttpResponse {
|
||||
HttpResponse::NotImplemented().body("")
|
||||
}
|
||||
|
||||
pub fn configure(config: &mut ServiceConfig) {
|
||||
config.service(landing).service(sign_in).service(logout);
|
||||
}
|
10
web/src/routes/mod.rs
Normal file
10
web/src/routes/mod.rs
Normal file
@ -0,0 +1,10 @@
|
||||
mod admin;
|
||||
mod public;
|
||||
|
||||
use actix_web::web::ServiceConfig;
|
||||
|
||||
pub fn configure(config: &mut ServiceConfig) {
|
||||
config
|
||||
.configure(public::configure)
|
||||
.configure(admin::configure);
|
||||
}
|
11
web/src/routes/public.rs
Normal file
11
web/src/routes/public.rs
Normal file
@ -0,0 +1,11 @@
|
||||
use actix_web::web::ServiceConfig;
|
||||
use actix_web::{get, HttpResponse};
|
||||
|
||||
#[get("/")]
|
||||
async fn landing() -> HttpResponse {
|
||||
HttpResponse::NotImplemented().body("")
|
||||
}
|
||||
|
||||
pub fn configure(config: &mut ServiceConfig) {
|
||||
config.service(landing);
|
||||
}
|
Loading…
Reference in New Issue
Block a user