From 1ecbdde2c04dfb5c45025f9b1b87b3f89960b594 Mon Sep 17 00:00:00 2001 From: MCorange Date: Wed, 14 Jan 2026 00:00:12 +0200 Subject: [PATCH] Implement more tables, add more page templates, initial working db example --- Cargo.lock | 71 ++++++++ Cargo.toml | 4 +- .../2026-01-13-095817-0000_users/up.sql | 4 +- .../2026-01-13-095838-0000_clients/up.sql | 18 +- .../up.sql | 1 + .../down.sql | 1 + .../up.sql | 7 + .../down.sql | 2 + .../up.sql | 8 + .../2026-01-13-095855-0000_tickets/up.sql | 10 +- .../2026-01-13-101601-0000_services/down.sql | 2 - .../2026-01-13-101601-0000_services/up.sql | 7 - .../down.sql | 1 + .../up.sql | 11 ++ .../down.sql | 1 + .../2026-01-13-191646-0000_attachments/up.sql | 9 + src/db/mod.rs | 24 ++- src/db/models.rs | 171 ++++++++++++++++++ src/db/schema.rs | 75 ++++++-- src/main.rs | 2 +- src/web/mod.rs | 9 +- src/web/pages/clients/mod.rs | 55 ++++++ src/web/pages/inventory.rs | 51 ------ .../pages/{clients.rs => inventory/mod.rs} | 25 +-- src/web/pages/login.rs | 4 +- src/web/pages/{tickets.rs => tickets/mod.rs} | 25 +-- static/arch.png | Bin 72779 -> 0 bytes static/{index.css => base.css} | 17 -- static/login.css | 18 ++ templates/base.html | 3 +- templates/clients/client.html | 7 + templates/clients/index.html | 31 ++++ templates/error.html | 5 + templates/home.html | 5 + templates/inventory/catalog.html | 7 + templates/inventory/index.html | 7 + templates/inventory/transfer.html | 7 + templates/login.html | 4 + templates/tickets/closed.html | 7 + templates/tickets/create.html | 7 + templates/tickets/index.html | 7 + 41 files changed, 583 insertions(+), 147 deletions(-) create mode 100644 migrations/2026-01-13-095853-0000_service_catalog/down.sql create mode 100644 migrations/2026-01-13-095853-0000_service_catalog/up.sql create mode 100644 migrations/2026-01-13-095854-0000_assigned_services/down.sql create mode 100644 migrations/2026-01-13-095854-0000_assigned_services/up.sql delete mode 100644 migrations/2026-01-13-101601-0000_services/down.sql delete mode 100644 migrations/2026-01-13-101601-0000_services/up.sql create mode 100644 migrations/2026-01-13-190735-0000_ticket_comments/down.sql create mode 100644 migrations/2026-01-13-190735-0000_ticket_comments/up.sql create mode 100644 migrations/2026-01-13-191646-0000_attachments/down.sql create mode 100644 migrations/2026-01-13-191646-0000_attachments/up.sql create mode 100644 src/db/models.rs create mode 100644 src/web/pages/clients/mod.rs delete mode 100644 src/web/pages/inventory.rs rename src/web/pages/{clients.rs => inventory/mod.rs} (68%) rename src/web/pages/{tickets.rs => tickets/mod.rs} (68%) delete mode 100755 static/arch.png rename static/{index.css => base.css} (69%) create mode 100644 static/login.css create mode 100644 templates/clients/client.html create mode 100644 templates/clients/index.html create mode 100644 templates/inventory/catalog.html create mode 100644 templates/inventory/index.html create mode 100644 templates/inventory/transfer.html create mode 100644 templates/tickets/closed.html create mode 100644 templates/tickets/create.html create mode 100644 templates/tickets/index.html diff --git a/Cargo.lock b/Cargo.lock index 901c20a..177f5be 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -466,6 +466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ececcb659e7ba858fb4f10388c250a7252eb0a27373f1a72b8748afdd248e587" dependencies = [ "powerfmt", + "serde_core", ] [[package]] @@ -482,6 +483,7 @@ dependencies = [ "itoa", "libc", "pq-sys", + "r2d2", "time", "uuid", ] @@ -625,8 +627,10 @@ dependencies = [ "env_logger", "ipnet", "log", + "r2d2", "serde", "serde_json", + "time", "tokio", "toml", "tower", @@ -1024,6 +1028,15 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6373607a59f0be73a39b6fe456b8192fcc3585f602af20751600e974dd455e77" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" @@ -1127,6 +1140,29 @@ version = "1.70.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "384b8ab6d37215f3c5301a95a4accb5d64aa607f1fcb26a11b5303878451b4fe" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1225,6 +1261,17 @@ version = "5.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "69cdb34c158ceb288df11e18b4bd39de994f6657d83847bdffdbd7f346754b0f" +[[package]] +name = "r2d2" +version = "0.8.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51de85fb3fb6524929c8a2eb85e6b6d363de4e8c48f9e2c2eac4944abc181c93" +dependencies = [ + "log", + "parking_lot", + "scheduled-thread-pool", +] + [[package]] name = "rand" version = "0.9.2" @@ -1254,6 +1301,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags", +] + [[package]] name = "regex" version = "1.12.2" @@ -1301,6 +1357,21 @@ version = "1.0.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984" +[[package]] +name = "scheduled-thread-pool" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3cbc66816425a074528352f5789333ecff06ca41b36b0b0efdfbb29edc391a19" +dependencies = [ + "parking_lot", +] + +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "serde" version = "1.0.228" diff --git a/Cargo.toml b/Cargo.toml index aa636da..14a0701 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,13 +9,15 @@ askama = "0.15.1" axum = { version = "0.8.8", features = ["macros", "ws"] } camino = "1.2.2" clap = { version = "4.5.54", features = ["derive"] } -diesel = { version = "2.3.5", features = ["uuid", "time", "postgres", "ipnet-address"] } +diesel = { version = "2.3.5", features = ["uuid", "time", "postgres", "ipnet-address", "r2d2"] } diesel_migrations = { version = "2.3.1", features = ["postgres"] } env_logger = "0.11.8" ipnet = "2.11.0" log = "0.4.29" +r2d2 = "0.8.10" serde = { version = "1.0.228", features = ["derive"] } serde_json = "1.0.149" +time = { version = "0.3.45", features = ["macros", "serde"] } tokio = { version = "1.49.0", features = ["io-util", "macros", "net", "rt-multi-thread", "time"] } toml = "0.9.11" tower = { version = "0.5.3", features = ["full"] } diff --git a/migrations/2026-01-13-095817-0000_users/up.sql b/migrations/2026-01-13-095817-0000_users/up.sql index 3cb8c4a..0e89ac8 100644 --- a/migrations/2026-01-13-095817-0000_users/up.sql +++ b/migrations/2026-01-13-095817-0000_users/up.sql @@ -13,6 +13,6 @@ CREATE TABLE IF NOT EXISTS users ( created_at TIMESTAMPTZ NOT NULL DEFAULT now(), last_login_at TIMESTAMPTZ, - -- u128 bitfield for permissions - permissions NUMERIC(39,0) NOT NULL DEFAULT 0 + -- i64 bitfield for permissions + permissions BIGINT NOT NULL DEFAULT 0 ) diff --git a/migrations/2026-01-13-095838-0000_clients/up.sql b/migrations/2026-01-13-095838-0000_clients/up.sql index b2ed366..99a688e 100644 --- a/migrations/2026-01-13-095838-0000_clients/up.sql +++ b/migrations/2026-01-13-095838-0000_clients/up.sql @@ -5,15 +5,15 @@ CREATE TABLE IF NOT EXISTS clients ( first_name TEXT NOT NULL, last_name TEXT NOT NULL, - date_of_birth DATE, - phone_number TEXT, - gov_id_number TEXT, - house_number TEXT, - address_line TEXT, - city TEXT, - state TEXT, - postal_code TEXT, - country TEXT, + date_of_birth DATE NOT NULL, + phone_number TEXT NOT NULL, + gov_id_number TEXT NOT NULL, + house_number TEXT NOT NULL, + address_line TEXT NOT NULL, + city TEXT NOT NULL, + state TEXT NOT NULL, + postal_code TEXT NOT NULL, + country TEXT NOT NULL, worker_user_id BIGINT, diff --git a/migrations/2026-01-13-095843-0000_inventory_catalog/up.sql b/migrations/2026-01-13-095843-0000_inventory_catalog/up.sql index 4c77ca4..c896864 100644 --- a/migrations/2026-01-13-095843-0000_inventory_catalog/up.sql +++ b/migrations/2026-01-13-095843-0000_inventory_catalog/up.sql @@ -2,5 +2,6 @@ CREATE TABLE IF NOT EXISTS inventory_catalog ( id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, name TEXT NOT NULL, description TEXT, + code TEXT NOT NULL, created_at TIMESTAMPTZ NOT NULL DEFAULT now() ) diff --git a/migrations/2026-01-13-095853-0000_service_catalog/down.sql b/migrations/2026-01-13-095853-0000_service_catalog/down.sql new file mode 100644 index 0000000..a828564 --- /dev/null +++ b/migrations/2026-01-13-095853-0000_service_catalog/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS service_catalog; diff --git a/migrations/2026-01-13-095853-0000_service_catalog/up.sql b/migrations/2026-01-13-095853-0000_service_catalog/up.sql new file mode 100644 index 0000000..ac91547 --- /dev/null +++ b/migrations/2026-01-13-095853-0000_service_catalog/up.sql @@ -0,0 +1,7 @@ +CREATE TABLE IF NOT EXISTS service_catalog ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + name TEXT NOT NULL, + description TEXT, + value_string TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now() +) diff --git a/migrations/2026-01-13-095854-0000_assigned_services/down.sql b/migrations/2026-01-13-095854-0000_assigned_services/down.sql new file mode 100644 index 0000000..77711f5 --- /dev/null +++ b/migrations/2026-01-13-095854-0000_assigned_services/down.sql @@ -0,0 +1,2 @@ +DROP TABLE IF EXISTS assigned_services; + diff --git a/migrations/2026-01-13-095854-0000_assigned_services/up.sql b/migrations/2026-01-13-095854-0000_assigned_services/up.sql new file mode 100644 index 0000000..6602078 --- /dev/null +++ b/migrations/2026-01-13-095854-0000_assigned_services/up.sql @@ -0,0 +1,8 @@ +CREATE TABLE IF NOT EXISTS assigned_services ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + client_id BIGINT NOT NULL, + catalog_id BIGINT NOT NULL, + + CONSTRAINT fk_client_id FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE, + CONSTRAINT fk_catalog_id FOREIGN KEY (catalog_id) REFERENCES service_catalog(id) ON DELETE CASCADE +) diff --git a/migrations/2026-01-13-095855-0000_tickets/up.sql b/migrations/2026-01-13-095855-0000_tickets/up.sql index c5053d7..a5ddd28 100644 --- a/migrations/2026-01-13-095855-0000_tickets/up.sql +++ b/migrations/2026-01-13-095855-0000_tickets/up.sql @@ -1,3 +1,11 @@ CREATE TABLE IF NOT EXISTS tickets ( - id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + title TEXT NOT NULL, + description TEXT, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + service_id BIGINT NOT NULL, + created_by_user_id BIGINT NOT NULL, + + CONSTRAINT fk_service_id FOREIGN KEY (service_id) REFERENCES assigned_services(id) ON DELETE CASCADE, + CONSTRAINT fk_user_id FOREIGN KEY (created_by_user_id) REFERENCES users(id) ON DELETE CASCADE ) diff --git a/migrations/2026-01-13-101601-0000_services/down.sql b/migrations/2026-01-13-101601-0000_services/down.sql deleted file mode 100644 index 49ef0d0..0000000 --- a/migrations/2026-01-13-101601-0000_services/down.sql +++ /dev/null @@ -1,2 +0,0 @@ -DROP TABLE IF EXISTS services; - diff --git a/migrations/2026-01-13-101601-0000_services/up.sql b/migrations/2026-01-13-101601-0000_services/up.sql deleted file mode 100644 index af48d55..0000000 --- a/migrations/2026-01-13-101601-0000_services/up.sql +++ /dev/null @@ -1,7 +0,0 @@ -CREATE TABLE IF NOT EXISTS services ( - id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, - name TEXT NOT NULL, - client_id BIGINT NOT NULL, - - CONSTRAINT fk_client_id FOREIGN KEY (client_id) REFERENCES clients(id) ON DELETE CASCADE -) diff --git a/migrations/2026-01-13-190735-0000_ticket_comments/down.sql b/migrations/2026-01-13-190735-0000_ticket_comments/down.sql new file mode 100644 index 0000000..3207a1a --- /dev/null +++ b/migrations/2026-01-13-190735-0000_ticket_comments/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS ticket_comments; diff --git a/migrations/2026-01-13-190735-0000_ticket_comments/up.sql b/migrations/2026-01-13-190735-0000_ticket_comments/up.sql new file mode 100644 index 0000000..f864a8e --- /dev/null +++ b/migrations/2026-01-13-190735-0000_ticket_comments/up.sql @@ -0,0 +1,11 @@ +CREATE TABLE IF NOT EXISTS ticket_comments ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + user_id BIGINT NOT NULL, + ticket_id BIGINT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + modified_at TIMESTAMPTZ, + content TEXT, + + CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + CONSTRAINT fk_ticket_id FOREIGN KEY (ticket_id) REFERENCES tickets(id) ON DELETE CASCADE +) diff --git a/migrations/2026-01-13-191646-0000_attachments/down.sql b/migrations/2026-01-13-191646-0000_attachments/down.sql new file mode 100644 index 0000000..318e120 --- /dev/null +++ b/migrations/2026-01-13-191646-0000_attachments/down.sql @@ -0,0 +1 @@ +DROP TABLE IF EXISTS attachments; diff --git a/migrations/2026-01-13-191646-0000_attachments/up.sql b/migrations/2026-01-13-191646-0000_attachments/up.sql new file mode 100644 index 0000000..e9ad158 --- /dev/null +++ b/migrations/2026-01-13-191646-0000_attachments/up.sql @@ -0,0 +1,9 @@ +CREATE TABLE IF NOT EXISTS attachments ( + id BIGINT GENERATED ALWAYS AS IDENTITY PRIMARY KEY, + user_id BIGINT NOT NULL, + comment_id BIGINT NOT NULL, + created_at TIMESTAMPTZ NOT NULL DEFAULT now(), + -- stored in file storage by attachment id + CONSTRAINT fk_user_id FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE, + CONSTRAINT fk_comment_id FOREIGN KEY (comment_id) REFERENCES ticket_comments(id) ON DELETE CASCADE +) diff --git a/src/db/mod.rs b/src/db/mod.rs index a6a27b2..5541c21 100644 --- a/src/db/mod.rs +++ b/src/db/mod.rs @@ -1,19 +1,31 @@ -use diesel::{Connection, PgConnection}; +use diesel::{Connection, PgConnection, r2d2::ConnectionManager}; use diesel_migrations::{EmbeddedMigrations, MigrationHarness, embed_migrations}; +use r2d2::Pool; pub mod schema; +pub mod models; pub const MIGRATIONS: EmbeddedMigrations = embed_migrations!("./migrations"); -fn run_migrations(conn: &mut impl MigrationHarness) { + +pub type DbPool = Pool>; + +fn run_migrations(pool: &mut DbPool) { + let mut conn = pool + .get() + .expect("failed to get db connection :3"); conn.run_pending_migrations(MIGRATIONS).unwrap(); log::info!("Running migrations"); } -pub fn start(cfg: &crate::config::Config) -> anyhow::Result { - let mut connection = PgConnection::establish(&cfg.database_url()?.to_string())?; - run_migrations(&mut connection); - Ok(connection) +pub fn start(cfg: &crate::config::Config) -> anyhow::Result { + let manager = ConnectionManager::::new(&cfg.database_url()?.to_string()); + let mut pool = Pool::builder() + .build(manager) + .expect("failed to create pool :3"); + + run_migrations(&mut pool); + Ok(pool) } diff --git a/src/db/models.rs b/src/db/models.rs new file mode 100644 index 0000000..b73246b --- /dev/null +++ b/src/db/models.rs @@ -0,0 +1,171 @@ +use diesel::prelude::*; + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(User, foreign_key=worker_user_id))] +#[diesel(table_name = super::schema::clients)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Client { + pub id: i64, + pub email: String, + pub first_name: String, + pub last_name: String, + pub date_of_birth: time::Date, + pub phone_number: String, + pub gov_id_number: String, + pub house_number: String, + pub address_line: String, + pub city: String, + pub state: String, + pub postal_code: String, + pub country: String, + pub worker_user_id: Option, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(User))] +#[diesel(belongs_to(Warehouse))] +#[diesel(table_name = super::schema::assigned_warehouse_managers)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct AssignedWarehouseManager { + pub id: i64, + pub user_id: i64, + pub warehouse_id: i64, + pub assigned_at: time::OffsetDateTime, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(User))] +#[diesel(table_name = super::schema::attachments)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Attachment { + pub id: i64, + pub user_id: i64, + pub comment_id: i64, + pub created_at: time::OffsetDateTime, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(Warehouse))] +#[diesel(belongs_to(InventoryCatalogEntry, foreign_key=catalog_id))] +#[diesel(table_name = super::schema::inventory)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Inventory { + pub id: i64, + pub warehouse_id: i64, + pub catalog_id: i64, + pub count: i64 +} + +#[derive(Queryable, Selectable)] +#[diesel(table_name = super::schema::inventory_catalog)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct InventoryCatalogEntry { + pub id: i64, + pub name: String, + pub code: String, + pub description: Option, + pub created_at: time::OffsetDateTime, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(Client))] +#[diesel(table_name = super::schema::invoices)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Invoice { + pub id: i64, + pub client_id: i64, + pub amount: f32 +} + +#[derive(Queryable, Selectable)] +#[diesel(table_name = super::schema::service_catalog)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct ServiceCatalogEntry { + pub id: i64, + pub name: String, + pub description: Option, + pub value_string: Option, + pub created_at: time::OffsetDateTime, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(Client))] +#[diesel(belongs_to(ServiceCatalogEntry, foreign_key=catalog_id))] +#[diesel(table_name = super::schema::assigned_services)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct AssignedService { + pub id: i64, + pub client_id: i64, + pub catalog_id: i64, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(User))] +#[diesel(belongs_to(Ticket))] +#[diesel(table_name = super::schema::ticket_comments)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct TicketComment { + pub id: i64, + pub user_id: i64, + pub ticket_id: i64, + pub created_at: time::OffsetDateTime, + pub modified_at: Option, + pub content: Option +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(AssignedService, foreign_key=service_id))] +#[diesel(table_name = super::schema::tickets)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Ticket { + pub id: i64, + pub title: String, + pub description: Option, + pub created_at: time::OffsetDateTime, + pub created_by_user_id: i64, + pub service_id: i64 +} + +#[derive(Queryable, Selectable)] +#[diesel(table_name = super::schema::users)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct User { + pub id: i64, + pub username: String, + pub email: String, + pub password_hash: String, + pub password_salt: String, + pub first_name: String, + pub last_name: String, + pub display_name: Option, + pub date_of_birth: Option, + pub phone_number: Option, + pub created_at: time::OffsetDateTime, + pub last_login_at: Option, + pub permissions: i64, +} + +#[derive(Queryable, Selectable, Associations)] +#[diesel(belongs_to(User))] +#[diesel(belongs_to(Warehouse))] +#[diesel(table_name = super::schema::warehouse_actions)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct WarehouseAction { + pub id: i64, + pub user_id: i64, + pub warehouse_id: i64, + pub count: i64, + pub reason: String, + pub timestamp: time::OffsetDateTime, +} + +#[derive(Queryable, Selectable)] +#[diesel(table_name = super::schema::warehouses)] +#[diesel(check_for_backend(diesel::pg::Pg))] +pub struct Warehouse { + pub id: i64, + pub name: String, + pub created_at: time::OffsetDateTime, +} + + diff --git a/src/db/schema.rs b/src/db/schema.rs index fc0768c..df11c30 100644 --- a/src/db/schema.rs +++ b/src/db/schema.rs @@ -1,5 +1,14 @@ // @generated automatically by Diesel CLI. +diesel::table! { + assigned_services (id) { + id -> Int8, + name -> Text, + client_id -> Int8, + catalog_id -> Int8, + } +} + diesel::table! { assigned_warehouse_managers (id) { id -> Int8, @@ -9,21 +18,30 @@ diesel::table! { } } +diesel::table! { + attachments (id) { + id -> Int8, + user_id -> Int8, + comment_id -> Int8, + created_at -> Timestamptz, + } +} + diesel::table! { clients (id) { id -> Int8, email -> Text, first_name -> Text, last_name -> Text, - date_of_birth -> Nullable, - phone_number -> Nullable, - gov_id_number -> Nullable, - house_number -> Nullable, - address_line -> Nullable, - city -> Nullable, - state -> Nullable, - postal_code -> Nullable, - country -> Nullable, + date_of_birth -> Date, + phone_number -> Text, + gov_id_number -> Text, + house_number -> Text, + address_line -> Text, + city -> Text, + state -> Text, + postal_code -> Text, + country -> Text, worker_user_id -> Nullable, } } @@ -42,6 +60,7 @@ diesel::table! { id -> Int8, name -> Text, description -> Nullable, + code -> Text, created_at -> Timestamptz, } } @@ -55,16 +74,34 @@ diesel::table! { } diesel::table! { - services (id) { + service_catalog (id) { id -> Int8, name -> Text, - client_id -> Int8, + description -> Nullable, + value_string -> Nullable, + created_at -> Timestamptz, + } +} + +diesel::table! { + ticket_comments (id) { + id -> Int8, + user_id -> Int8, + ticket_id -> Int8, + created_at -> Timestamptz, + modified_at -> Nullable, + content -> Nullable, } } diesel::table! { tickets (id) { id -> Int8, + title -> Text, + description -> Nullable, + created_at -> Timestamptz, + service_id -> Int8, + created_by_user_id -> Int8, } } @@ -82,7 +119,7 @@ diesel::table! { phone_number -> Nullable, created_at -> Timestamptz, last_login_at -> Nullable, - permissions -> Numeric, + permissions -> Int8, } } @@ -105,23 +142,33 @@ diesel::table! { } } +diesel::joinable!(assigned_services -> clients (client_id)); +diesel::joinable!(assigned_services -> service_catalog (catalog_id)); diesel::joinable!(assigned_warehouse_managers -> users (user_id)); diesel::joinable!(assigned_warehouse_managers -> warehouses (warehouse_id)); +diesel::joinable!(attachments -> ticket_comments (comment_id)); +diesel::joinable!(attachments -> users (user_id)); diesel::joinable!(clients -> users (worker_user_id)); diesel::joinable!(inventory -> inventory_catalog (catalog_id)); diesel::joinable!(inventory -> warehouses (warehouse_id)); diesel::joinable!(invoices -> clients (client_id)); -diesel::joinable!(services -> clients (client_id)); +diesel::joinable!(ticket_comments -> tickets (ticket_id)); +diesel::joinable!(ticket_comments -> users (user_id)); +diesel::joinable!(tickets -> assigned_services (service_id)); +diesel::joinable!(tickets -> users (created_by_user_id)); diesel::joinable!(warehouse_actions -> users (user_id)); diesel::joinable!(warehouse_actions -> warehouses (warehouse_id)); diesel::allow_tables_to_appear_in_same_query!( + assigned_services, assigned_warehouse_managers, + attachments, clients, inventory, inventory_catalog, invoices, - services, + service_catalog, + ticket_comments, tickets, users, warehouse_actions, diff --git a/src/main.rs b/src/main.rs index 6f840c6..4171e42 100644 --- a/src/main.rs +++ b/src/main.rs @@ -19,6 +19,6 @@ async fn main() -> anyhow::Result<()> { } let db = db::start(&cfg)?; - web::start(&cfg).await?; + web::start(&cfg, db).await?; Ok(()) } diff --git a/src/web/mod.rs b/src/web/mod.rs index ba6e387..ee1cca8 100644 --- a/src/web/mod.rs +++ b/src/web/mod.rs @@ -1,22 +1,27 @@ use axum::{Router, routing::get}; +use diesel::PgConnection; use tower::ServiceBuilder; use tower_http::services::ServeDir; +use crate::db::DbPool; + pub mod pages; -pub async fn start(cfg: &crate::config::Config) -> anyhow::Result<()> { +pub async fn start(cfg: &crate::config::Config, db: DbPool) -> anyhow::Result<()> { let addr = format!("{}:{}", cfg.web.host, cfg.web.port); let app = Router::new() .route("/", get(pages::home::get_page)) .route("/login", get(pages::login::get_page)) + .route("/clients", get(pages::clients::get_page)) .nest_service( "/static", ServiceBuilder::new() .service(ServeDir::new("static")) - ); + ) + .with_state(db); let listener = tokio::net::TcpListener::bind(&addr).await.unwrap(); log::info!("Listening on http://{addr}"); diff --git a/src/web/pages/clients/mod.rs b/src/web/pages/clients/mod.rs new file mode 100644 index 0000000..c0749a9 --- /dev/null +++ b/src/web/pages/clients/mod.rs @@ -0,0 +1,55 @@ +use askama::Template; +use axum::extract::State; +use axum::response::{Html, IntoResponse, Response}; +use axum::http::StatusCode; + +use crate::db::DbPool; +use crate::db::models::Client; +use crate::web::pages::{BaseTemplate, BaseTemplateCtx}; + +#[derive(Template)] +#[template(path = "clients/index.html")] +pub struct PageTemplate { + pub ctx: BaseTemplateCtx, + pub clients: Vec +} + +impl BaseTemplate for PageTemplate { + fn ctx(&self) -> &BaseTemplateCtx { + &self.ctx + } + fn ctx_mut(&mut self) -> &mut BaseTemplateCtx { + &mut self.ctx + } + +} + +#[axum::debug_handler] +pub async fn get_page(State(pool): State) -> Response { + async fn inner(pool: &DbPool) -> anyhow::Result<(StatusCode, String)> { + use diesel::prelude::*; + use crate::db::schema::clients::dsl::*; + + let results = clients + .order(id.asc()) + .limit(50) + .load::(&mut pool.get()?)?; + + let mut template = PageTemplate { + ctx: Default::default(), + clients: results + }; + + template.set_title("Clients"); + + Ok((StatusCode::OK, template.render()?)) + } + + match inner(&pool).await { + Ok((status, s)) => (status, Html(s)).into_response(), + Err(e) => { + let s = crate::web::pages::error::get_error_page(e.to_string()).await; + (StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response() + } + } +} diff --git a/src/web/pages/inventory.rs b/src/web/pages/inventory.rs deleted file mode 100644 index 60466b7..0000000 --- a/src/web/pages/inventory.rs +++ /dev/null @@ -1,51 +0,0 @@ - - - -use askama::Template; -use axum::response::{Html, IntoResponse, Response}; - -use axum::{ - routing::{get, post}, - http::StatusCode, - Json, Router, -}; - -use crate::web::pages::{BaseTemplate, BaseTemplateCtx}; - -#[derive(Template)] -#[template(path = "home.html")] -pub struct HomeTemplate { - pub ctx: BaseTemplateCtx, - -} - -impl BaseTemplate for HomeTemplate { - fn ctx(&self) -> &BaseTemplateCtx { - &self.ctx - } - fn ctx_mut(&mut self) -> &mut BaseTemplateCtx { - &mut self.ctx - } - -} - -#[axum::debug_handler] -pub async fn get_page() -> Response { - fn inner() -> anyhow::Result<(StatusCode, String)> { - let mut template = HomeTemplate { - ctx: Default::default() - }; - - template.set_title("Home"); - - Ok((StatusCode::OK, template.render()?)) - } - - match inner() { - Ok((status, s)) => (status, Html(s)).into_response(), - Err(e) => { - let s = crate::web::pages::error::get_error_page(e.to_string()).await; - (StatusCode::INTERNAL_SERVER_ERROR, Html(s)).into_response() - } - } -} diff --git a/src/web/pages/clients.rs b/src/web/pages/inventory/mod.rs similarity index 68% rename from src/web/pages/clients.rs rename to src/web/pages/inventory/mod.rs index 4c73322..c67aa11 100644 --- a/src/web/pages/clients.rs +++ b/src/web/pages/inventory/mod.rs @@ -1,22 +1,15 @@ - - - use askama::Template; +use axum::extract::State; use axum::response::{Html, IntoResponse, Response}; +use axum::http::StatusCode; -use axum::{ - routing::{get, post}, - http::StatusCode, - Json, Router, -}; - +use crate::db::DbPool; use crate::web::pages::{BaseTemplate, BaseTemplateCtx}; #[derive(Template)] -#[template(path = "home.html")] +#[template(path = "inventory/index.html")] pub struct PageTemplate { pub ctx: BaseTemplateCtx, - } impl BaseTemplate for PageTemplate { @@ -30,18 +23,18 @@ impl BaseTemplate for PageTemplate { } #[axum::debug_handler] -pub async fn get_page() -> Response { - fn inner() -> anyhow::Result<(StatusCode, String)> { +pub async fn get_page(State(pool): State) -> Response { + async fn inner(_pool: &DbPool) -> anyhow::Result<(StatusCode, String)> { let mut template = PageTemplate { - ctx: Default::default() + ctx: Default::default(), }; - template.set_title("Home"); + template.set_title("Clients"); Ok((StatusCode::OK, template.render()?)) } - match inner() { + match inner(&pool).await { Ok((status, s)) => (status, Html(s)).into_response(), Err(e) => { let s = crate::web::pages::error::get_error_page(e.to_string()).await; diff --git a/src/web/pages/login.rs b/src/web/pages/login.rs index b1dfcbd..d7aaabc 100644 --- a/src/web/pages/login.rs +++ b/src/web/pages/login.rs @@ -1,4 +1,5 @@ use askama::Template; +use axum::extract::State; use axum::response::{Html, IntoResponse, Response}; use axum::{ @@ -7,6 +8,7 @@ use axum::{ Json, Router, }; +use crate::db::DbPool; use crate::web::pages::{BaseTemplate, BaseTemplateCtx}; #[derive(Template)] @@ -27,7 +29,7 @@ impl BaseTemplate for PageTemplate { } #[axum::debug_handler] -pub async fn get_page() -> Response { +pub async fn get_page(State(_db): State) -> Response { fn inner() -> anyhow::Result<(StatusCode, String)> { let mut template = PageTemplate { ctx: Default::default() diff --git a/src/web/pages/tickets.rs b/src/web/pages/tickets/mod.rs similarity index 68% rename from src/web/pages/tickets.rs rename to src/web/pages/tickets/mod.rs index 0ecb5a3..f5460dd 100644 --- a/src/web/pages/tickets.rs +++ b/src/web/pages/tickets/mod.rs @@ -1,22 +1,15 @@ - - - use askama::Template; +use axum::extract::State; use axum::response::{Html, IntoResponse, Response}; +use axum::http::StatusCode; -use axum::{ - routing::{get, post}, - http::StatusCode, - Json, Router, -}; - +use crate::db::DbPool; use crate::web::pages::{BaseTemplate, BaseTemplateCtx}; #[derive(Template)] -#[template(path = "home.html")] +#[template(path = "tickets/index.html")] pub struct PageTemplate { pub ctx: BaseTemplateCtx, - } impl BaseTemplate for PageTemplate { @@ -30,18 +23,18 @@ impl BaseTemplate for PageTemplate { } #[axum::debug_handler] -pub async fn get_page() -> Response { - fn inner() -> anyhow::Result<(StatusCode, String)> { +pub async fn get_page(State(pool): State) -> Response { + async fn inner(_pool: &DbPool) -> anyhow::Result<(StatusCode, String)> { let mut template = PageTemplate { - ctx: Default::default() + ctx: Default::default(), }; - template.set_title("Tickets"); + template.set_title("Clients"); Ok((StatusCode::OK, template.render()?)) } - match inner() { + match inner(&pool).await { Ok((status, s)) => (status, Html(s)).into_response(), Err(e) => { let s = crate::web::pages::error::get_error_page(e.to_string()).await; diff --git a/static/arch.png b/static/arch.png deleted file mode 100755 index 01fc39d2acf967cf165fb26d24c1dc05d40a8819..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 72779 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 DLmc4% diff --git a/static/index.css b/static/base.css similarity index 69% rename from static/index.css rename to static/base.css index 3eda125..eae63e1 100644 --- a/static/index.css +++ b/static/base.css @@ -50,21 +50,4 @@ footer { } -.login-form { - background: gray; - position: absolute; - top: 50%; - left: 50%; - transform: translate(-50%, -50%); - padding: 10px; -} - -.login-form input[type="email"],input[type="password"] { - width: 95%; -} - -.login-form input[type="submit"] { - width: 98%; - margin-top: 10px; -} diff --git a/static/login.css b/static/login.css new file mode 100644 index 0000000..8c9bc5a --- /dev/null +++ b/static/login.css @@ -0,0 +1,18 @@ +.login-form { + + background: gray; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + padding: 10px; +} + +.login-form input[type="email"],input[type="password"] { + width: 95%; +} + +.login-form input[type="submit"] { + width: 98%; + margin-top: 10px; +} diff --git a/templates/base.html b/templates/base.html index 86574ca..22cf4a4 100644 --- a/templates/base.html +++ b/templates/base.html @@ -3,7 +3,8 @@ {{ self.title() }} - + + {% block headers %}{% endblock %} {% include "header.html" %} diff --git a/templates/clients/client.html b/templates/clients/client.html new file mode 100644 index 0000000..5a84a91 --- /dev/null +++ b/templates/clients/client.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block headers %} +{% endblock %} + +{% block content %} +Hewwo wowld!!!! +{% endblock %} diff --git a/templates/clients/index.html b/templates/clients/index.html new file mode 100644 index 0000000..f00c234 --- /dev/null +++ b/templates/clients/index.html @@ -0,0 +1,31 @@ +{% extends "base.html" %} +{% block headers %} +{% endblock %} + +{% block content %} + + + + + + + + + {% for client in clients %} + + + + + + + + {% endfor %} +
First NameLast NameAddressNumberEmail
{{ client.first_name }}{{ client.last_name }} + {{ client.country}} + {{ client.city}} + {{ client.state}} + {{ client.address_line}} + {{ client.house_number}} + {{ client.postal_code}} + {{ client.phone_number }}{{ client.email }}
+{% endblock %} diff --git a/templates/error.html b/templates/error.html index 23b7ba1..b49081a 100644 --- a/templates/error.html +++ b/templates/error.html @@ -1,5 +1,10 @@ {% extends "base.html" %} +{% block headers %} +{% endblock %} + + + {% block content %} A server error happened: {{ error }} {% endblock %} diff --git a/templates/home.html b/templates/home.html index 3a2bea3..3fa596b 100644 --- a/templates/home.html +++ b/templates/home.html @@ -1,5 +1,10 @@ {% extends "base.html" %} +{% block headers %} +{% endblock %} + + + {% block content %} Hewo world diff --git a/templates/inventory/catalog.html b/templates/inventory/catalog.html new file mode 100644 index 0000000..5a84a91 --- /dev/null +++ b/templates/inventory/catalog.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block headers %} +{% endblock %} + +{% block content %} +Hewwo wowld!!!! +{% endblock %} diff --git a/templates/inventory/index.html b/templates/inventory/index.html new file mode 100644 index 0000000..5a84a91 --- /dev/null +++ b/templates/inventory/index.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block headers %} +{% endblock %} + +{% block content %} +Hewwo wowld!!!! +{% endblock %} diff --git a/templates/inventory/transfer.html b/templates/inventory/transfer.html new file mode 100644 index 0000000..5a84a91 --- /dev/null +++ b/templates/inventory/transfer.html @@ -0,0 +1,7 @@ +{% extends "base.html" %} +{% block headers %} +{% endblock %} + +{% block content %} +Hewwo wowld!!!! +{% endblock %} diff --git a/templates/login.html b/templates/login.html index 44f83f6..b95cde4 100644 --- a/templates/login.html +++ b/templates/login.html @@ -1,5 +1,9 @@ {% extends "base.html" %} +{% block headers %} + +{% endblock %} + {% block content %}