Skip to content

Commit

Permalink
f
Browse files Browse the repository at this point in the history
  • Loading branch information
svemat01 committed Nov 27, 2024
1 parent 38f6bac commit 9974013
Show file tree
Hide file tree
Showing 20 changed files with 506 additions and 261 deletions.
12 changes: 12 additions & 0 deletions engine/migrations/0001_init.down.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
DROP TABLE IF EXISTS items_to_tags;
DROP TABLE IF EXISTS product_media;
DROP TABLE IF EXISTS item_media;
DROP TABLE IF EXISTS item_fields;
DROP TABLE IF EXISTS items;
DROP TABLE IF EXISTS media;
DROP TABLE IF EXISTS field_definitions;
DROP TABLE IF EXISTS tags;
DROP TABLE IF EXISTS products;
DROP TABLE IF EXISTS locations;
DROP TABLE IF EXISTS sessions;
DROP TABLE IF EXISTS users;
7 changes: 0 additions & 7 deletions engine/migrations/0001_init.sql

This file was deleted.

111 changes: 111 additions & 0 deletions engine/migrations/0001_init.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,111 @@
-- Independent tables first

-- Create Users table
CREATE TABLE users (
user_id SERIAL PRIMARY KEY, -- Unique identifier for each user
oauth_sub TEXT NOT NULL UNIQUE, -- OAuth subject identifier from authentication provider
oauth_data JSONB NOT NULL, -- JSON data containing OAuth provider information
nickname TEXT, -- Optional display name for the user
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the user record was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the user record was last updated
);

-- Insert a system user
INSERT INTO users (user_id, oauth_sub, oauth_data, nickname) VALUES (0, '$$SYSTEM$$', '{}', 'System');

-- Create Sessions table
CREATE TABLE sessions (
session_id TEXT PRIMARY KEY, -- Unique session identifier
user_id INTEGER NOT NULL, -- Reference to the user this session belongs to
user_agent TEXT NOT NULL, -- Browser/client information
user_ip TEXT NOT NULL, -- IP address of the client
valid BOOLEAN NOT NULL DEFAULT TRUE, -- Whether the session is still valid
last_access TIMESTAMP WITH TIME ZONE NOT NULL DEFAULT CURRENT_TIMESTAMP, -- When the session was last used
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the session was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the session was last updated
FOREIGN KEY (user_id) REFERENCES users(user_id) ON DELETE CASCADE -- Links session to user, deletes session when user is deleted
);

CREATE TABLE locations (
location_id SERIAL PRIMARY KEY, -- Unique identifier for each location
name TEXT NOT NULL, -- Name of the location
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the location was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the location was last updated
);

CREATE TABLE products (
product_id SERIAL PRIMARY KEY, -- Unique identifier for each product
name TEXT NOT NULL, -- Name of the product
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the product was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the product was last updated
);

CREATE TABLE tags (
tag_id SERIAL PRIMARY KEY, -- Unique identifier for each tag
name TEXT NOT NULL, -- Name of the tag
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the tag was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the tag was last updated
);

CREATE TABLE field_definitions (
definition_id TEXT PRIMARY KEY, -- Unique identifier for each field definition
kind TEXT NOT NULL, -- Type of the field
name TEXT NOT NULL, -- Name of the field
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the field definition was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the field definition was last updated
);

CREATE TABLE media (
media_id SERIAL PRIMARY KEY, -- Unique identifier for each media item
description TEXT, -- Description of the media
url TEXT NOT NULL, -- URL where the media can be accessed
kind TEXT NOT NULL, -- Type of media (image, video, etc.)
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the media was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the media was last updated
);

-- Tables with single foreign key dependencies
CREATE TABLE items (
item_id TEXT PRIMARY KEY, -- Unique identifier for each item
name TEXT NOT NULL, -- Name of the item
location_id INTEGER, -- Reference to the location where this item is stored
product_id INTEGER, -- Optional reference to the associated product
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the item was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP -- When the item was last updated
);

-- Junction tables and tables with multiple dependencies
CREATE TABLE item_fields (
item_id TEXT NOT NULL, -- Reference to the item
definition_id TEXT NOT NULL, -- Reference to the field definition
value JSONB NOT NULL, -- The value of the field for this item
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the field value was created
updated_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP, -- When the field value was last updated
PRIMARY KEY (item_id, definition_id),
FOREIGN KEY (item_id) REFERENCES items(item_id) ON DELETE CASCADE, -- Links field to item, deletes field when item is deleted
FOREIGN KEY (definition_id) REFERENCES field_definitions(definition_id) ON DELETE CASCADE -- Links field to definition, deletes field when definition is deleted
);

CREATE TABLE item_media (
item_id TEXT NOT NULL, -- Reference to the item
media_id INTEGER NOT NULL, -- Reference to the media
PRIMARY KEY (item_id, media_id)
-- FOREIGN KEY (item_id) REFERENCES items(item_id) ON DELETE CASCADE, -- Links media to item, deletes link when item is deleted
-- FOREIGN KEY (media_id) REFERENCES media(media_id) ON DELETE CASCADE -- Links media to item, deletes link when media is deleted
);

CREATE TABLE product_media (
product_id INTEGER NOT NULL, -- Reference to the product
media_id INTEGER NOT NULL, -- Reference to the media
PRIMARY KEY (product_id, media_id)
-- FOREIGN KEY (product_id) REFERENCES products(product_id) ON DELETE CASCADE, -- Links media to product, deletes link when product is deleted
-- FOREIGN KEY (media_id) REFERENCES media(media_id) ON DELETE CASCADE -- Links media to product, deletes link when media is deleted
);

CREATE TABLE items_to_tags (
item_id TEXT NOT NULL, -- Reference to the item
tag_id INTEGER NOT NULL, -- Reference to the tag
PRIMARY KEY (item_id, tag_id),
FOREIGN KEY (item_id) REFERENCES items(item_id) ON DELETE CASCADE, -- Links tag to item, deletes link when item is deleted
FOREIGN KEY (tag_id) REFERENCES tags(tag_id) ON DELETE CASCADE -- Links tag to item, deletes link when tag is deleted
);
9 changes: 0 additions & 9 deletions engine/migrations/0002_sessions.sql

This file was deleted.

25 changes: 0 additions & 25 deletions engine/migrations/0003_property.sql

This file was deleted.

27 changes: 0 additions & 27 deletions engine/migrations/0004_media.sql

This file was deleted.

62 changes: 62 additions & 0 deletions engine/src/models/field_definitions.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
use serde::{Deserialize, Serialize};
use sqlx::prelude::*;

#[derive(sqlx::Type, poem_openapi::Enum, Debug, Clone, Serialize, Deserialize)]
#[sqlx(type_name = "text")]
#[sqlx(rename_all = "lowercase")]
pub enum FieldKind {
String,
Number,
Boolean,
Json,
}

impl std::fmt::Display for FieldKind {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.to_string())
}
}

impl From<String> for FieldKind {
fn from(s: String) -> Self {
match s.to_lowercase().as_str() {
"string" => FieldKind::String,
"number" => FieldKind::Number,
"boolean" => FieldKind::Boolean,
"json" => FieldKind::Json,
_ => FieldKind::String,
}
}
}

impl From<FieldKind> for String {
fn from(kind: FieldKind) -> Self {
kind.to_string().to_lowercase()
}
}

#[derive(sqlx::FromRow, poem_openapi::Object, Debug, Clone, Serialize, Deserialize)]
pub struct FieldDefinition {
pub definition_id: String,
pub kind: FieldKind,
pub name: String,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}

impl FieldDefinition {
pub async fn create(
kind: FieldKind,
name: String,
database: &Database,
) -> Result<FieldDefinition, sqlx::Error> {
sqlx::query_as!(
FieldDefinition,
"INSERT INTO field_definitions (kind, name) VALUES ($1, $2) RETURNING *",
kind.to_string(),
name
)
.fetch_one(&database.pool)
.await
}
}
84 changes: 84 additions & 0 deletions engine/src/models/items.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
use serde::{Deserialize, Serialize};
use sqlx::prelude::*;

#[derive(sqlx::FromRow, poem_openapi::Object, Debug, Clone, Serialize, Deserialize)]
pub struct Item {
pub item_id: String,
pub name: String,
pub location_id: Option<i32>,
pub product_id: Option<i32>,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}

impl Item {
pub async fn create(
item_id: String,
name: String,
location_id: Option<i32>,
product_id: Option<i32>,
database: &Database,
) -> Result<Item, sqlx::Error> {
sqlx::query_as!(
Item,
"INSERT INTO items (item_id, name, location_id, product_id) VALUES ($1, $2, $3, $4) RETURNING *",
item_id,
name,
location_id,
product_id
)
.fetch_one(&database.pool)
.await
}
}

#[derive(sqlx::FromRow, poem_openapi::Object, Debug, Clone, Serialize, Deserialize)]
pub struct ItemField {
pub item_id: String,
pub definition_id: String,
pub value: serde_json::Value,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}

impl ItemField {
pub async fn create(
item_id: String,
definition_id: String,
value: serde_json::Value,
database: &Database,
) -> Result<ItemField, sqlx::Error> {
sqlx::query_as!(
ItemField,
"INSERT INTO item_fields (item_id, definition_id, value) VALUES ($1, $2, $3) RETURNING *",
item_id,
definition_id,
value
)
.fetch_one(&database.pool)
.await
}
}

#[derive(sqlx::FromRow, poem_openapi::Object, Debug, Clone, Serialize, Deserialize)]
pub struct ItemMedia {
pub item_id: String,
pub media_id: i32,
}

impl ItemMedia {
pub async fn create(
item_id: String,
media_id: i32,
database: &Database,
) -> Result<ItemMedia, sqlx::Error> {
sqlx::query_as!(
ItemMedia,
"INSERT INTO item_media (item_id, media_id) VALUES ($1, $2) RETURNING *",
item_id,
media_id
)
.fetch_one(&database.pool)
.await
}
}
22 changes: 22 additions & 0 deletions engine/src/models/locations.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
use serde::{Deserialize, Serialize};
use sqlx::prelude::*;

#[derive(sqlx::FromRow, poem_openapi::Object, Debug, Clone, Serialize, Deserialize)]
pub struct Location {
pub location_id: i32,
pub name: String,
pub created_at: Option<chrono::DateTime<chrono::Utc>>,
pub updated_at: Option<chrono::DateTime<chrono::Utc>>,
}

impl Location {
pub async fn create(name: String, database: &Database) -> Result<Location, sqlx::Error> {
sqlx::query_as!(
Location,
"INSERT INTO locations (name) VALUES ($1) RETURNING *",
name
)
.fetch_one(&database.pool)
.await
}
}
Loading

0 comments on commit 9974013

Please sign in to comment.