Implement categories
This commit is contained in:
parent
864f9842f0
commit
df1594e3f4
@ -24,4 +24,4 @@ thiserror = { version = "1.0.37" }
|
||||
tokio = { version = "1.21.2", features = ['full'] }
|
||||
tracing = { version = "0.1.37" }
|
||||
whatlang = { version = "0.16.2" }
|
||||
strum = { version = "0.24.1", features = ['strum_macros', 'default'] }
|
||||
strum = { version = "0.24.1", features = ['strum_macros', 'default', 'derive'] }
|
||||
|
@ -1,4 +1,58 @@
|
||||
use strum::IntoStaticStr;
|
||||
use rumqttc::QoS;
|
||||
|
||||
use crate::AsyncClient;
|
||||
|
||||
impl AsyncClient {
|
||||
pub async fn emit_category_created(&self, category: &model::v2::Category) {
|
||||
self.publish_or_log(Topic::CategoryCreated, QoS::AtLeastOnce, true, category)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn emit_category_updated(&self, category: &model::v2::Category) {
|
||||
self.publish_or_log(Topic::CategoryUpdated, QoS::AtLeastOnce, true, category)
|
||||
.await
|
||||
}
|
||||
|
||||
pub async fn emit_category_deleted(&self, category_id: &model::v2::CategoryId) {
|
||||
self.publish_or_log(Topic::CategoryDeleted, QoS::AtLeastOnce, true, category_id)
|
||||
.await
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, PartialOrd, PartialEq, serde::Serialize, serde::Deserialize)]
|
||||
pub enum Topic {
|
||||
CategoryCreated,
|
||||
CategoryUpdated,
|
||||
CategoryDeleted,
|
||||
}
|
||||
|
||||
impl Topic {
|
||||
pub fn to_str(self) -> &'static str {
|
||||
match self {
|
||||
Topic::CategoryCreated => "category/created",
|
||||
Topic::CategoryUpdated => "category/updated",
|
||||
Topic::CategoryDeleted => "category/deleted",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Into<String> for Topic {
|
||||
fn into(self) -> String {
|
||||
self.to_str().into()
|
||||
}
|
||||
}
|
||||
|
||||
impl<'s> PartialEq<&'s str> for Topic {
|
||||
fn eq(&self, other: &&'s str) -> bool {
|
||||
self.to_str() == *other
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialEq<String> for Topic {
|
||||
fn eq(&self, other: &String) -> bool {
|
||||
self.to_str() == other.as_str()
|
||||
}
|
||||
}
|
||||
|
||||
pub mod create_category {
|
||||
use model::v2::*;
|
||||
@ -32,7 +86,9 @@ pub mod delete_category {
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Details {}
|
||||
pub struct Details {
|
||||
pub category: Option<Category>,
|
||||
}
|
||||
|
||||
pub type Output = Result<Details, Error>;
|
||||
}
|
||||
@ -53,8 +109,7 @@ pub mod update_category {
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Details {
|
||||
pub limit: Limit,
|
||||
pub offset: Offset,
|
||||
pub category: Category,
|
||||
}
|
||||
|
||||
pub type Output = Result<Details, Error>;
|
||||
@ -66,7 +121,10 @@ pub mod all_categories {
|
||||
use crate::stocks::Error;
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Input {}
|
||||
pub struct Input {
|
||||
pub limit: Limit,
|
||||
pub offset: Offset,
|
||||
}
|
||||
|
||||
#[derive(Debug, serde::Serialize, serde::Deserialize)]
|
||||
pub struct Details {
|
||||
@ -75,12 +133,3 @@ pub mod all_categories {
|
||||
|
||||
pub type Output = Result<Details, Error>;
|
||||
}
|
||||
|
||||
#[derive(
|
||||
Copy, Clone, Debug, PartialOrd, PartialEq, serde::Serialize, serde::Deserialize, IntoStaticStr,
|
||||
)]
|
||||
pub enum Topic {
|
||||
CategoryCreated,
|
||||
CategoryUpdated,
|
||||
CategoryDeleted,
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ pub mod product_variant;
|
||||
|
||||
pub use categories::*;
|
||||
pub use load::*;
|
||||
use model::v2::{ProductId, ProductVariantId};
|
||||
use model::v2::{CategoryId, ProductId, ProductVariantId};
|
||||
pub use product::*;
|
||||
pub use product_photo::*;
|
||||
pub use product_stock::*;
|
||||
@ -56,7 +56,13 @@ pub enum Error {
|
||||
#[error("Failed to load product variants {0:?}")]
|
||||
FindProductVariants(Vec<ProductVariantId>),
|
||||
#[error("Failed to load all categories")]
|
||||
Categories,
|
||||
AllCategories,
|
||||
#[error("Failed to crate products category")]
|
||||
CreateCategory,
|
||||
#[error("Failed to delete products category {0:?}")]
|
||||
DeleteCategory(CategoryId),
|
||||
#[error("Failed to update products category {0:?}")]
|
||||
UpdateCategory(CategoryId),
|
||||
}
|
||||
|
||||
pub mod rpc {
|
||||
@ -67,10 +73,13 @@ pub mod rpc {
|
||||
use crate::stocks::product_photo::*;
|
||||
use crate::stocks::product_stock::*;
|
||||
use crate::stocks::product_variant::*;
|
||||
use crate::stocks::{all_categories, create_category, delete_category, update_category};
|
||||
|
||||
#[tarpc::service]
|
||||
pub trait Stocks {
|
||||
// Product
|
||||
// ####################
|
||||
// PRODUCT
|
||||
// ####################
|
||||
/// Create new product.
|
||||
async fn create_product(input: create_product::Input) -> create_product::Output;
|
||||
/// Update product information.
|
||||
@ -78,7 +87,21 @@ pub mod rpc {
|
||||
/// Delete product.
|
||||
async fn delete_product(input: delete_product::Input) -> delete_product::Output;
|
||||
|
||||
// Product variant
|
||||
// ####################
|
||||
// DETAILED PRODUCT
|
||||
// ####################
|
||||
/// Single product with stock size and photos
|
||||
async fn detailed_product(input: detailed_product::Input) -> detailed_product::Output;
|
||||
|
||||
/// List of products with stock size and photos
|
||||
async fn detailed_products(input: detailed_products::Input) -> detailed_products::Output;
|
||||
|
||||
/// List of products for shopping cart
|
||||
async fn shopping_cart_products(input: find_products::Input) -> find_products::Output;
|
||||
|
||||
// ####################
|
||||
// PRODUCT VARIANTS
|
||||
// ####################
|
||||
/// Create new variant of the product.
|
||||
async fn create_product_variant(
|
||||
input: create_product_variant::Input,
|
||||
@ -92,7 +115,14 @@ pub mod rpc {
|
||||
input: delete_product_variant::Input,
|
||||
) -> delete_product_variant::Output;
|
||||
|
||||
// Product photo
|
||||
/// List of products variants for shopping cart
|
||||
async fn shopping_cart_product_variants(
|
||||
input: find_product_variants::Input,
|
||||
) -> find_product_variants::Output;
|
||||
|
||||
// ####################
|
||||
// PRODUCT PHOTO
|
||||
// ####################
|
||||
/// Load all photos
|
||||
async fn all_product_photo(input: all_product_photo::Input) -> all_product_photo::Output;
|
||||
|
||||
@ -104,7 +134,9 @@ pub mod rpc {
|
||||
input: delete_product_photo::Input,
|
||||
) -> delete_product_photo::Output;
|
||||
|
||||
// Product stock
|
||||
// ####################
|
||||
// PRODUCT STOCK
|
||||
// ####################
|
||||
/// Create product stock.
|
||||
async fn create_product_stock(
|
||||
input: create_product_stock::Input,
|
||||
@ -114,22 +146,20 @@ pub mod rpc {
|
||||
input: update_product_stock::Input,
|
||||
) -> update_product_stock::Output;
|
||||
|
||||
// Load
|
||||
/// Single product with stock size and photos
|
||||
async fn detailed_product(input: detailed_product::Input) -> detailed_product::Output;
|
||||
// ####################
|
||||
// CATEGORIES
|
||||
// ####################
|
||||
/// Create new products category
|
||||
async fn create_category(input: create_category::Input) -> create_category::Output;
|
||||
|
||||
/// List of products with stock size and photos
|
||||
async fn detailed_products(input: detailed_products::Input) -> detailed_products::Output;
|
||||
/// Delete existing products category
|
||||
async fn delete_category(input: delete_category::Input) -> delete_category::Output;
|
||||
|
||||
/// List of products for shopping cart
|
||||
async fn shopping_cart_products(input: find_products::Input) -> find_products::Output;
|
||||
///Change existing products category
|
||||
async fn update_category(input: update_category::Input) -> update_category::Output;
|
||||
|
||||
/// List of products variants for shopping cart
|
||||
async fn shopping_cart_product_variants(
|
||||
input: find_product_variants::Input,
|
||||
) -> find_product_variants::Output;
|
||||
|
||||
// async fn
|
||||
/// List of call products categories
|
||||
async fn all_categories(input: all_categories::Input) -> all_categories::Output;
|
||||
}
|
||||
|
||||
pub async fn create_client(config: SharedAppConfig) -> StocksClient {
|
||||
|
@ -1626,6 +1626,7 @@ pub mod v2 {
|
||||
#[derive(
|
||||
Debug,
|
||||
Clone,
|
||||
Copy,
|
||||
Default,
|
||||
PartialOrd,
|
||||
PartialEq,
|
||||
|
176
crates/stock_manager/src/actions/categories.rs
Normal file
176
crates/stock_manager/src/actions/categories.rs
Normal file
@ -0,0 +1,176 @@
|
||||
use channels::stocks::{all_categories, create_category, delete_category, update_category, Error};
|
||||
use channels::AsyncClient;
|
||||
use config::SharedAppConfig;
|
||||
use db_utils::PgT;
|
||||
|
||||
use crate::db::{AllCategories, CreateCategory, Database, DeleteCategory, UpdateCategory};
|
||||
use crate::{begin_t, dbm_run};
|
||||
|
||||
pub async fn create_category(
|
||||
input: create_category::Input,
|
||||
db: Database,
|
||||
_mqtt: AsyncClient,
|
||||
_config: SharedAppConfig,
|
||||
) -> create_category::Output {
|
||||
let mut t = begin_t!(db, Error::InternalServerError);
|
||||
|
||||
let res = inner_create_category(input, &mut t).await;
|
||||
|
||||
match res {
|
||||
Ok(v) => {
|
||||
if let Err(e) = t.commit().await {
|
||||
tracing::error!("{}", e);
|
||||
return Err(Error::InternalServerError);
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let Err(e) = t.rollback().await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn inner_create_category(
|
||||
input: create_category::Input,
|
||||
t: &mut PgT<'_>,
|
||||
) -> create_category::Output {
|
||||
let dbm = CreateCategory {
|
||||
parent_id: input.parent_id,
|
||||
name: input.name,
|
||||
key: input.key,
|
||||
svg: input.svg,
|
||||
};
|
||||
Ok(create_category::Details {
|
||||
product: dbm_run!(dbm, t, Error::CreateCategory),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn delete_category(
|
||||
input: delete_category::Input,
|
||||
db: Database,
|
||||
_mqtt: AsyncClient,
|
||||
_config: SharedAppConfig,
|
||||
) -> delete_category::Output {
|
||||
let mut t = begin_t!(db, Error::InternalServerError);
|
||||
|
||||
let res = inner_delete_category(input, &mut t).await;
|
||||
|
||||
match res {
|
||||
Ok(v) => {
|
||||
if let Err(e) = t.commit().await {
|
||||
tracing::error!("{}", e);
|
||||
return Err(Error::InternalServerError);
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let Err(e) = t.rollback().await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn inner_delete_category(
|
||||
input: delete_category::Input,
|
||||
t: &mut PgT<'_>,
|
||||
) -> delete_category::Output {
|
||||
let dbm = DeleteCategory {
|
||||
category_id: input.category_id,
|
||||
};
|
||||
Ok(delete_category::Details {
|
||||
category: dbm_run!(dbm, t, Error::DeleteCategory(input.category_id)),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn update_category(
|
||||
input: update_category::Input,
|
||||
db: Database,
|
||||
_mqtt: AsyncClient,
|
||||
_config: SharedAppConfig,
|
||||
) -> update_category::Output {
|
||||
let mut t = begin_t!(db, Error::InternalServerError);
|
||||
|
||||
let res = inner_update_category(input, &mut t).await;
|
||||
|
||||
match res {
|
||||
Ok(v) => {
|
||||
if let Err(e) = t.commit().await {
|
||||
tracing::error!("{}", e);
|
||||
return Err(Error::InternalServerError);
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let Err(e) = t.rollback().await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn inner_update_category(
|
||||
input: update_category::Input,
|
||||
t: &mut PgT<'_>,
|
||||
) -> update_category::Output {
|
||||
let dbm = UpdateCategory {
|
||||
id: input.id,
|
||||
parent_id: input.parent_id,
|
||||
name: input.name,
|
||||
key: input.key,
|
||||
svg: input.svg,
|
||||
};
|
||||
Ok(update_category::Details {
|
||||
category: dbm_run!(dbm, t, Error::UpdateCategory(input.id)),
|
||||
})
|
||||
}
|
||||
|
||||
pub async fn all_categories(
|
||||
input: all_categories::Input,
|
||||
db: Database,
|
||||
_mqtt: AsyncClient,
|
||||
_config: SharedAppConfig,
|
||||
) -> all_categories::Output {
|
||||
let mut t = begin_t!(db, Error::InternalServerError);
|
||||
|
||||
let res = inner_all_categories(input, &mut t).await;
|
||||
|
||||
match res {
|
||||
Ok(v) => {
|
||||
if let Err(e) = t.commit().await {
|
||||
tracing::error!("{}", e);
|
||||
return Err(Error::InternalServerError);
|
||||
} else {
|
||||
Ok(v)
|
||||
}
|
||||
}
|
||||
Err(e) => {
|
||||
if let Err(e) = t.rollback().await {
|
||||
tracing::error!("{}", e);
|
||||
}
|
||||
Err(e)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn inner_all_categories(
|
||||
input: all_categories::Input,
|
||||
t: &mut PgT<'_>,
|
||||
) -> all_categories::Output {
|
||||
let dbm = AllCategories {
|
||||
limit: input.limit,
|
||||
offset: input.offset,
|
||||
};
|
||||
|
||||
Ok(all_categories::Details {
|
||||
categories: dbm_run!(dbm, t, Error::AllCategories),
|
||||
})
|
||||
}
|
@ -61,7 +61,7 @@ async fn inner_detailed_product(
|
||||
limit: Limit::from_u32(2000),
|
||||
offset: Offset::from_u32(0),
|
||||
};
|
||||
let categories = dbm_run!(dbm, t, Error::Categories);
|
||||
let categories = dbm_run!(dbm, t, Error::AllCategories);
|
||||
|
||||
let mut variants = utils::vec_to_hash_vec(variants, 10, |p| p.product_id);
|
||||
let mut stocks = utils::vec_to_hash_vec(stocks, 10, |s| s.product_variant_id);
|
||||
@ -146,7 +146,7 @@ async fn inner_detailed_products(
|
||||
limit: Limit::from_u32(2000),
|
||||
offset: Offset::from_u32(0),
|
||||
};
|
||||
let categories = dbm_run!(dbm, t, Error::Categories);
|
||||
let categories = dbm_run!(dbm, t, Error::AllCategories);
|
||||
|
||||
let mut variants = utils::vec_to_hash_vec(variants, 10, |p| p.product_id);
|
||||
let mut stocks = utils::vec_to_hash_vec(stocks, 10, |s| s.product_variant_id);
|
||||
|
@ -1,9 +1,11 @@
|
||||
pub mod categories;
|
||||
pub mod load;
|
||||
pub mod product;
|
||||
pub mod product_photo;
|
||||
pub mod product_stock;
|
||||
pub mod product_variant;
|
||||
|
||||
pub use categories::*;
|
||||
pub use load::*;
|
||||
pub use product::*;
|
||||
pub use product_photo::*;
|
||||
|
@ -8,6 +8,10 @@ pub enum Error {
|
||||
All,
|
||||
#[error("Failed to create category")]
|
||||
Create,
|
||||
#[error("Failed to delete category {0:?}")]
|
||||
Delete(CategoryId),
|
||||
#[error("Failed to update category {0:?}")]
|
||||
Update(CategoryId),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
@ -46,6 +50,74 @@ RETURNING id,
|
||||
}
|
||||
}
|
||||
|
||||
pub struct UpdateCategory {
|
||||
pub id: CategoryId,
|
||||
pub parent_id: Option<CategoryId>,
|
||||
pub name: CategoryName,
|
||||
pub key: CategoryKey,
|
||||
pub svg: CategorySvg,
|
||||
}
|
||||
|
||||
impl UpdateCategory {
|
||||
/// Update category
|
||||
///
|
||||
/// ## Example
|
||||
///
|
||||
/// ```rust
|
||||
/// async fn change(t: &mut PgT<'_>) {
|
||||
/// let dbm = UpdateCategory {};
|
||||
/// dbm.run(t).await;
|
||||
/// }
|
||||
/// ```
|
||||
pub async fn run(self, t: &mut PgT<'_>) -> Result<Category> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
UPDATE categories
|
||||
SET parent_id = $2,
|
||||
name = $3,
|
||||
key = $4,
|
||||
svg = $5
|
||||
WHERE id = $1
|
||||
RETURNING id,
|
||||
parent_id,
|
||||
name,
|
||||
key,
|
||||
svg
|
||||
"#,
|
||||
)
|
||||
.bind(self.id)
|
||||
.bind(self.parent_id)
|
||||
.bind(self.name)
|
||||
.bind(self.key)
|
||||
.bind(self.svg)
|
||||
.fetch_one(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("{e:?}");
|
||||
dbg!(e);
|
||||
Error::Update(self.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct DeleteCategory {
|
||||
pub category_id: CategoryId,
|
||||
}
|
||||
|
||||
impl DeleteCategory {
|
||||
pub async fn run(self, t: &mut PgT<'_>) -> Result<Option<Category>> {
|
||||
sqlx::query_as("DELETE FROM categories WHERE id = $1")
|
||||
.bind(self.category_id)
|
||||
.fetch_optional(t)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::error!("{}", e);
|
||||
dbg!(e);
|
||||
Error::Delete(self.category_id)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct AllCategories {
|
||||
pub limit: Limit,
|
||||
pub offset: Offset,
|
||||
@ -84,7 +156,7 @@ mod tests {
|
||||
use model::v2::{Category, CategoryName};
|
||||
use model::{Limit, Offset};
|
||||
|
||||
use crate::db::{AllCategories, CreateCategory, Database};
|
||||
use crate::db::{AllCategories, CreateCategory, Database, DeleteCategory, UpdateCategory};
|
||||
|
||||
struct NoOpts;
|
||||
|
||||
@ -121,4 +193,88 @@ mod tests {
|
||||
|
||||
assert_eq!(res.unwrap().len(), 3);
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn delete_one() {
|
||||
testx::db_t_ref!(t);
|
||||
|
||||
test_category("Electronics".into(), &mut t).await;
|
||||
let second = test_category("Shoes".into(), &mut t).await;
|
||||
test_category("Pants".into(), &mut t).await;
|
||||
|
||||
let len1 = AllCategories {
|
||||
limit: Limit::from_u32(2000),
|
||||
offset: Offset::from_u32(0),
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
|
||||
let deleted1 = DeleteCategory {
|
||||
category_id: second.id,
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
let deleted2 = DeleteCategory {
|
||||
category_id: second.id,
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
|
||||
let len2 = AllCategories {
|
||||
limit: Limit::from_u32(2000),
|
||||
offset: Offset::from_u32(0),
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
|
||||
testx::db_rollback!(t);
|
||||
|
||||
let len1 = len1.unwrap();
|
||||
let deleted1 = deleted1.unwrap();
|
||||
let deleted2 = deleted2.unwrap();
|
||||
let len2 = len2.unwrap();
|
||||
|
||||
assert_eq!(len1.len(), 3);
|
||||
assert_eq!(len2.len(), 2);
|
||||
assert!(deleted1.is_some());
|
||||
assert!(deleted2.is_none());
|
||||
}
|
||||
|
||||
#[tokio::test]
|
||||
async fn update_one() {
|
||||
testx::db_t_ref!(t);
|
||||
|
||||
let first = test_category("Electronics".into(), &mut t).await;
|
||||
let second = test_category("Shoes".into(), &mut t).await;
|
||||
let third = test_category("Pants".into(), &mut t).await;
|
||||
|
||||
let res = UpdateCategory {
|
||||
id: second.id,
|
||||
parent_id: None,
|
||||
name: "Wearables".into(),
|
||||
key: second.key.clone(),
|
||||
svg: second.svg.clone(),
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
|
||||
let all = AllCategories {
|
||||
limit: Limit::from_u32(2000),
|
||||
offset: Offset::from_u32(0),
|
||||
}
|
||||
.run(&mut t)
|
||||
.await;
|
||||
|
||||
testx::db_rollback!(t);
|
||||
|
||||
let res = res.unwrap();
|
||||
let all = all.unwrap();
|
||||
|
||||
assert_eq!(res.name, "Wearables".into());
|
||||
assert_eq!(res.id, second.id);
|
||||
|
||||
assert_eq!(all[0].name, first.name);
|
||||
assert_eq!(all[1].name, "Wearables".into());
|
||||
assert_eq!(all[2].name, third.name);
|
||||
}
|
||||
}
|
||||
|
@ -2,75 +2,75 @@ use model::v2::*;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq, Eq, serde::Serialize, thiserror::Error)]
|
||||
pub enum Error {
|
||||
#[error("Unable to load all stocks")]
|
||||
All,
|
||||
// #[error("Unable to load all stocks")]
|
||||
// All,
|
||||
#[error("Unable to create stock")]
|
||||
Create,
|
||||
#[error("Unable to update stock {0:?}")]
|
||||
Update(StockId),
|
||||
#[error("Unable to delete stock {0:?}")]
|
||||
Delete(StockId),
|
||||
// #[error("Unable to delete stock {0:?}")]
|
||||
// Delete(StockId),
|
||||
// #[error("Unable to delete all stock for variant {0:?}")]
|
||||
// DeleteAllProductStocks(ProductId),
|
||||
#[error("Unable find stock for product")]
|
||||
ProductVariantStock,
|
||||
#[error("Stock {0:?} does not exists")]
|
||||
NotFound(StockId),
|
||||
// #[error("Stock {0:?} does not exists")]
|
||||
// NotFound(StockId),
|
||||
}
|
||||
|
||||
pub type Result<T> = std::result::Result<T, Error>;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct AllStocks {
|
||||
pub limit: i32,
|
||||
pub offset: i32,
|
||||
}
|
||||
|
||||
impl AllStocks {
|
||||
pub async fn run(self, pool: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> Result<Vec<Stock>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, product_variant_id, quantity, quantity_unit
|
||||
FROM stocks
|
||||
ORDER BY id ASC
|
||||
LIMIT $1 OFFSET $2
|
||||
"#,
|
||||
)
|
||||
.bind(self.limit)
|
||||
.bind(self.offset)
|
||||
.fetch_all(pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("{e:?}");
|
||||
Error::All
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct FindStock {
|
||||
pub id: StockId,
|
||||
}
|
||||
|
||||
impl FindStock {
|
||||
pub async fn run(self, pool: &mut sqlx::Transaction<'_, sqlx::Postgres>) -> Result<Stock> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
SELECT id, product_variant_id, quantity, quantity_unit
|
||||
FROM stocks
|
||||
WHERE id = $1
|
||||
"#,
|
||||
)
|
||||
.bind(self.id)
|
||||
.fetch_one(pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("{e:?}");
|
||||
dbg!(e);
|
||||
Error::NotFound(self.id)
|
||||
})
|
||||
}
|
||||
}
|
||||
// #[derive(Debug)]
|
||||
// pub struct AllStocks {
|
||||
// pub limit: i32,
|
||||
// pub offset: i32,
|
||||
// }
|
||||
//
|
||||
// impl AllStocks {
|
||||
// pub async fn run(self, pool: &mut sqlx::Transaction<'_, sqlx::Postgres>)
|
||||
// -> Result<Vec<Stock>> { sqlx::query_as(
|
||||
// r#"
|
||||
// SELECT id, product_variant_id, quantity, quantity_unit
|
||||
// FROM stocks
|
||||
// ORDER BY id ASC
|
||||
// LIMIT $1 OFFSET $2
|
||||
// "#,
|
||||
// )
|
||||
// .bind(self.limit)
|
||||
// .bind(self.offset)
|
||||
// .fetch_all(pool)
|
||||
// .await
|
||||
// .map_err(|e| {
|
||||
// tracing::warn!("{e:?}");
|
||||
// Error::All
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
//
|
||||
// #[derive(Debug)]
|
||||
// pub struct FindStock {
|
||||
// pub id: StockId,
|
||||
// }
|
||||
//
|
||||
// impl FindStock {
|
||||
// pub async fn run(self, pool: &mut sqlx::Transaction<'_, sqlx::Postgres>)
|
||||
// -> Result<Stock> { sqlx::query_as(
|
||||
// r#"
|
||||
// SELECT id, product_variant_id, quantity, quantity_unit
|
||||
// FROM stocks
|
||||
// WHERE id = $1
|
||||
// "#,
|
||||
// )
|
||||
// .bind(self.id)
|
||||
// .fetch_one(pool)
|
||||
// .await
|
||||
// .map_err(|e| {
|
||||
// tracing::warn!("{e:?}");
|
||||
// dbg!(e);
|
||||
// Error::NotFound(self.id)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct CreateStock {
|
||||
@ -134,32 +134,32 @@ RETURNING id, product_variant_id, quantity, quantity_unit
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DeleteStock {
|
||||
pub stock_id: StockId,
|
||||
}
|
||||
|
||||
impl DeleteStock {
|
||||
pub async fn run(
|
||||
self,
|
||||
pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
) -> Result<Option<Stock>> {
|
||||
sqlx::query_as(
|
||||
r#"
|
||||
DELETE FROM stocks
|
||||
WHERE id = $1
|
||||
RETURNING id, product_variant_id, quantity, quantity_unit
|
||||
"#,
|
||||
)
|
||||
.bind(self.stock_id)
|
||||
.fetch_optional(pool)
|
||||
.await
|
||||
.map_err(|e| {
|
||||
tracing::warn!("{e:?}");
|
||||
Error::Delete(self.stock_id)
|
||||
})
|
||||
}
|
||||
}
|
||||
// #[derive(Debug)]
|
||||
// pub struct DeleteStock {
|
||||
// pub stock_id: StockId,
|
||||
// }
|
||||
//
|
||||
// impl DeleteStock {
|
||||
// pub async fn run(
|
||||
// self,
|
||||
// pool: &mut sqlx::Transaction<'_, sqlx::Postgres>,
|
||||
// ) -> Result<Option<Stock>> {
|
||||
// sqlx::query_as(
|
||||
// r#"
|
||||
// DELETE FROM stocks
|
||||
// WHERE id = $1
|
||||
// RETURNING id, product_variant_id, quantity, quantity_unit
|
||||
// "#,
|
||||
// )
|
||||
// .bind(self.stock_id)
|
||||
// .fetch_optional(pool)
|
||||
// .await
|
||||
// .map_err(|e| {
|
||||
// tracing::warn!("{e:?}");
|
||||
// Error::Delete(self.stock_id)
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct ProductVariantsStock {
|
||||
|
@ -6,6 +6,7 @@ use crate::db::Database;
|
||||
use crate::rpc::rpc::StocksServer;
|
||||
|
||||
pub mod rpc {
|
||||
use channels::stocks::create_category::{Input, Output};
|
||||
use channels::stocks::rpc::Stocks;
|
||||
use channels::stocks::*;
|
||||
use config::SharedAppConfig;
|
||||
@ -46,6 +47,30 @@ pub mod rpc {
|
||||
actions::delete_product(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn detailed_product(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: detailed_product::Input,
|
||||
) -> detailed_product::Output {
|
||||
actions::detailed_product(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn detailed_products(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: detailed_products::Input,
|
||||
) -> detailed_products::Output {
|
||||
actions::detailed_products(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn shopping_cart_products(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: find_products::Input,
|
||||
) -> find_products::Output {
|
||||
actions::find_products(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn create_product_variant(
|
||||
self,
|
||||
_: context::Context,
|
||||
@ -70,6 +95,14 @@ pub mod rpc {
|
||||
actions::delete_product_variant(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn shopping_cart_product_variants(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: find_product_variants::Input,
|
||||
) -> find_product_variants::Output {
|
||||
actions::find_product_variants(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn all_product_photo(
|
||||
self,
|
||||
_: context::Context,
|
||||
@ -110,36 +143,32 @@ pub mod rpc {
|
||||
actions::update_product_stock(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn detailed_product(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: detailed_product::Input,
|
||||
) -> detailed_product::Output {
|
||||
actions::detailed_product(input, self.db, self.mqtt_client, self.config).await
|
||||
async fn create_category(self, _: context::Context, input: Input) -> Output {
|
||||
actions::create_category(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn detailed_products(
|
||||
async fn delete_category(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: detailed_products::Input,
|
||||
) -> detailed_products::Output {
|
||||
actions::detailed_products(input, self.db, self.mqtt_client, self.config).await
|
||||
input: delete_category::Input,
|
||||
) -> delete_category::Output {
|
||||
actions::delete_category(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn shopping_cart_products(
|
||||
async fn update_category(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: find_products::Input,
|
||||
) -> find_products::Output {
|
||||
actions::find_products(input, self.db, self.mqtt_client, self.config).await
|
||||
input: update_category::Input,
|
||||
) -> update_category::Output {
|
||||
actions::update_category(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
|
||||
async fn shopping_cart_product_variants(
|
||||
async fn all_categories(
|
||||
self,
|
||||
_: context::Context,
|
||||
input: find_product_variants::Input,
|
||||
) -> find_product_variants::Output {
|
||||
actions::find_product_variants(input, self.db, self.mqtt_client, self.config).await
|
||||
input: all_categories::Input,
|
||||
) -> all_categories::Output {
|
||||
actions::all_categories(input, self.db, self.mqtt_client, self.config).await
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user