about summary refs log tree commit diff stats
path: root/crates/rocie-server/src/storage/sql/insert
diff options
context:
space:
mode:
Diffstat (limited to 'crates/rocie-server/src/storage/sql/insert')
-rw-r--r--crates/rocie-server/src/storage/sql/insert/mod.rs22
-rw-r--r--crates/rocie-server/src/storage/sql/insert/product/mod.rs4
-rw-r--r--crates/rocie-server/src/storage/sql/insert/unit/mod.rs110
3 files changed, 132 insertions, 4 deletions
diff --git a/crates/rocie-server/src/storage/sql/insert/mod.rs b/crates/rocie-server/src/storage/sql/insert/mod.rs
index 99f1e71..eec6ad2 100644
--- a/crates/rocie-server/src/storage/sql/insert/mod.rs
+++ b/crates/rocie-server/src/storage/sql/insert/mod.rs
@@ -8,6 +8,7 @@ use serde::{Serialize, de::DeserializeOwned};
 use sqlx::{SqliteConnection, query};
 
 pub(crate) mod product;
+pub(crate) mod unit;
 
 pub(crate) trait Transactionable:
     Sized + std::fmt::Debug + Serialize + DeserializeOwned
@@ -77,7 +78,8 @@ impl<O: Transactionable> Operations<O> {
 }
 
 pub(crate) mod apply {
-    use actix_web::ResponseError;
+    use actix_web::{ResponseError, http::header::HeaderValue};
+    use log::error;
 
     use crate::storage::sql::insert::{Transactionable, add_operations_to_txn_log};
 
@@ -94,7 +96,23 @@ pub(crate) mod apply {
     }
 
     impl<O: Transactionable> ResponseError for Error<O> {
-        // TODO(@bpeetz): Actually do something with this. <2025-09-05>
+        fn status_code(&self) -> actix_web::http::StatusCode {
+            actix_web::http::StatusCode::INTERNAL_SERVER_ERROR
+        }
+
+        fn error_response(&self) -> actix_web::HttpResponse<actix_web::body::BoxBody> {
+            error!("Emmiting `INTERNAL_SERVER_ERROR`: {self}");
+            let mut res =
+                actix_web::HttpResponse::new(self.status_code()).set_body(self.to_string());
+
+            let mime = actix_web::mime::TEXT_PLAIN_UTF_8;
+            res.headers_mut().insert(
+                actix_web::http::header::CONTENT_TYPE,
+                HeaderValue::from_str(mime.to_string().as_str()).expect("Hard-coded conversion"),
+            );
+
+            res.set_body(actix_web::body::BoxBody::new(self.to_string()))
+        }
     }
 }
 
diff --git a/crates/rocie-server/src/storage/sql/insert/product/mod.rs b/crates/rocie-server/src/storage/sql/insert/product/mod.rs
index 562e809..b6dd604 100644
--- a/crates/rocie-server/src/storage/sql/insert/product/mod.rs
+++ b/crates/rocie-server/src/storage/sql/insert/product/mod.rs
@@ -115,14 +115,14 @@ impl Transactionable for Operation {
 pub(crate) mod undo {
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
-        #[error("Failed to execute sql statments")]
+        #[error("Failed to execute undo sql statments: {0}")]
         SqlError(#[from] sqlx::Error),
     }
 }
 pub(crate) mod apply {
     #[derive(thiserror::Error, Debug)]
     pub(crate) enum Error {
-        #[error("Failed to execute sql statments")]
+        #[error("Failed to execute apply sql statments: {0}")]
         SqlError(#[from] sqlx::Error),
     }
 }
diff --git a/crates/rocie-server/src/storage/sql/insert/unit/mod.rs b/crates/rocie-server/src/storage/sql/insert/unit/mod.rs
new file mode 100644
index 0000000..ba08487
--- /dev/null
+++ b/crates/rocie-server/src/storage/sql/insert/unit/mod.rs
@@ -0,0 +1,110 @@
+use serde::{Deserialize, Serialize};
+use sqlx::query;
+use uuid::Uuid;
+
+use crate::storage::sql::{insert::{Operations, Transactionable}, unit::{Unit, UnitId}};
+
+#[derive(Debug, Deserialize, Serialize)]
+pub(crate) enum Operation {
+    RegisterUnit {
+        id: UnitId,
+        full_name_singular: String,
+        full_name_plural: String,
+        short_name: String,
+        description: Option<String>,
+    },
+}
+
+impl Transactionable for Operation {
+    type ApplyError = apply::Error;
+    type UndoError = undo::Error;
+
+    async fn apply(self, txn: &mut sqlx::SqliteConnection) -> Result<(), apply::Error> {
+        match self {
+            Operation::RegisterUnit {
+                id,
+                full_name_singular,
+                full_name_plural,
+                short_name,
+                description,
+            } => {
+                query!(
+                    "
+                    INSERT INTO units (id, full_name_singular, full_name_plural, short_name, description)
+                    VALUES (?,?,?,?,?)
+",
+                    id, full_name_singular, full_name_plural, short_name, description,
+                )
+                .execute(txn)
+                .await?;
+            }
+        }
+        Ok(())
+    }
+
+    async fn undo(self, txn: &mut sqlx::SqliteConnection) -> Result<(), undo::Error> {
+        match self {
+            Operation::RegisterUnit {
+                id,
+                full_name_singular,
+                full_name_plural,
+                short_name,
+                description,
+            } => {
+                query!(
+                    "
+                    DELETE FROM units
+                    WHERE id = ? AND full_name_singular = ? AND full_name_plural = ? AND short_name = ? AND description = ?;
+",
+                    id, full_name_singular, full_name_plural, short_name, description,
+                )
+                .execute(txn)
+                .await?;
+            }
+        }
+        Ok(())
+    }
+}
+
+pub(crate) mod undo {
+    #[derive(thiserror::Error, Debug)]
+    pub(crate) enum Error {
+        #[error("Failed to execute undo sql statments: {0}")]
+        SqlError(#[from] sqlx::Error),
+    }
+}
+pub(crate) mod apply {
+    #[derive(thiserror::Error, Debug)]
+    pub(crate) enum Error {
+        #[error("Failed to execute apply sql statments: {0}")]
+        SqlError(#[from] sqlx::Error),
+    }
+}
+
+impl Unit {
+    pub(crate) fn register(
+        full_name_singular: String,
+        full_name_plural: String,
+        short_name: String,
+        description: Option<String>,
+        ops: &mut Operations<Operation>,
+    ) -> Self {
+        let id = UnitId::from(Uuid::new_v4());
+
+        ops.push(Operation::RegisterUnit {
+            id,
+            full_name_singular: full_name_singular.clone(),
+            full_name_plural: full_name_plural.clone(),
+            short_name: short_name.clone(),
+            description: description.clone(),
+        });
+
+        Self {
+            id,
+            full_name_singular,
+            full_name_plural,
+            short_name,
+            description,
+        }
+    }
+}