diff --git a/api/src/model/api.rs b/api/src/model/api.rs index 684ec77..7731e32 100644 --- a/api/src/model/api.rs +++ b/api/src/model/api.rs @@ -67,3 +67,60 @@ pub struct AccountOrder { pub order_id: Option, pub items: Vec, } + +#[derive(Serialize, Debug)] +pub struct ShoppingCartItem { + pub id: model::ShoppingCartId, + pub product_id: model::ProductId, + pub shopping_cart_id: model::ShoppingCartId, + pub quantity: model::Quantity, + pub quantity_unit: model::QuantityUnit, +} + +#[derive(Serialize, Debug)] +pub struct ShoppingCart { + pub id: model::ShoppingCartId, + pub buyer_id: AccountId, + pub payment_method: model::PaymentMethod, + pub state: model::ShoppingCartState, + pub items: Vec, +} + +impl From<(model::ShoppingCart, Vec)> for ShoppingCart { + fn from( + ( + model::ShoppingCart { + id, + buyer_id, + payment_method, + state, + }, + items, + ): (model::ShoppingCart, Vec), + ) -> Self { + Self { + id, + buyer_id, + payment_method, + state, + items: items + .into_iter() + .map( + |model::ShoppingCartItem { + id, + product_id, + shopping_cart_id, + quantity, + quantity_unit, + }| ShoppingCartItem { + id, + product_id, + shopping_cart_id, + quantity, + quantity_unit, + }, + ) + .collect(), + } + } +} diff --git a/api/src/opts.rs b/api/src/opts.rs index 89efdcc..b7ad20b 100644 --- a/api/src/opts.rs +++ b/api/src/opts.rs @@ -80,7 +80,10 @@ impl Default for Command { } } -pub struct ConfigInfo {} +#[derive(Options, Debug)] +pub struct ConfigInfo { + pub help: bool, +} #[derive(Options, Debug)] pub struct GenerateHashOpts { diff --git a/api/src/routes/public/api_v1/restricted.rs b/api/src/routes/public/api_v1/restricted.rs index 3c628aa..f8b3767 100644 --- a/api/src/routes/public/api_v1/restricted.rs +++ b/api/src/routes/public/api_v1/restricted.rs @@ -6,83 +6,42 @@ use actix_web_httpauth::extractors::bearer::BearerAuth; use crate::actors::cart_manager; use crate::actors::cart_manager::CartManager; use crate::database::Database; -use crate::model::{ - AccountId, ProductId, Quantity, QuantityUnit, ShoppingCart, ShoppingCartItem, - ShoppingCartItemId, -}; +use crate::model::{api, AccountId, ProductId, Quantity, QuantityUnit, ShoppingCartItemId}; use crate::payment_manager::PaymentManager; -use crate::routes::public::api_v1::ShoppingCartError; +use crate::routes::public::api_v1::{Error as ApiV1Error, ShoppingCartError}; use crate::routes::public::Error as PublicError; use crate::routes::{RequireUser, Result}; use crate::token_manager::TokenManager; -use crate::{database, model, payment_manager, query_pay, routes}; +use crate::{database, model, payment_manager, query_db, query_pay, routes}; #[get("/shopping-cart")] async fn shopping_cart( db: Data>, tm: Data>, credentials: BearerAuth, -) -> Result { +) -> Result> { let (token, _) = credentials.require_user(tm.into_inner()).await?; - match db - .send(database::EnsureActiveShoppingCart { + let cart: model::ShoppingCart = query_db!( + db, + database::EnsureActiveShoppingCart { buyer_id: AccountId::from(token.subject), - }) - .await - { - Ok(Ok(cart)) => Ok(HttpResponse::Ok().json(cart)), - Ok(Err(e)) => { - log::error!("{e}"); - Err(ShoppingCartError::Ensure.into()) - } - Err(e) => { - log::error!("{e:?}"); - Err(ShoppingCartError::Ensure.into()) - } - } -} - -#[get("/shopping-cart-items")] -async fn shopping_cart_items( - db: Data>, - tm: Data>, - credentials: BearerAuth, -) -> Result { - let (token, _) = credentials.require_user(tm.into_inner()).await?; - - let cart: ShoppingCart = match db - .send(database::EnsureActiveShoppingCart { - buyer_id: AccountId::from(token.subject), - }) - .await - { - Ok(Ok(cart)) => cart, - Ok(Err(e)) => { - log::error!("{e}"); - return Err(ShoppingCartError::Ensure.into()); - } - Err(e) => { - log::error!("{e:?}"); - return Err(ShoppingCartError::Ensure.into()); - } - }; - match db - .send(database::AccountShoppingCartItems { + }, + routes::Error::Public(PublicError::ApiV1(ApiV1Error::ShoppingCart( + ShoppingCartError::Ensure + ))) + ); + let items: Vec = query_db!( + db, + database::AccountShoppingCartItems { account_id: cart.buyer_id, shopping_cart_id: Some(cart.id), - }) - .await - { - Ok(Ok(items)) => Ok(HttpResponse::Ok().json(items)), - Ok(Err(e)) => { - log::error!("{e}"); - Err(ShoppingCartError::Ensure.into()) - } - Err(e) => { - log::error!("{e:?}"); - Err(ShoppingCartError::Ensure.into()) - } - } + }, + routes::Error::Public(PublicError::ApiV1(ApiV1Error::ShoppingCart( + ShoppingCartError::Ensure + ))) + ); + let cart = api::ShoppingCart::from((cart, items)); + Ok(Json(cart)) } #[derive(serde::Deserialize)] @@ -95,7 +54,7 @@ pub struct CreateItemInput { #[derive(serde::Serialize)] pub struct CreateItemOutput { pub success: bool, - pub shopping_cart_item: ShoppingCartItem, + pub shopping_cart_item: model::ShoppingCartItem, } #[post("/shopping-cart-item")] @@ -104,7 +63,7 @@ async fn create_cart_item( tm: Data>, credentials: BearerAuth, Json(payload): Json, -) -> Result { +) -> Result> { let (token, _) = credentials.require_user(tm.into_inner()).await?; match cart @@ -116,7 +75,7 @@ async fn create_cart_item( }) .await { - Ok(Ok(item)) => Ok(HttpResponse::Created().json(CreateItemOutput { + Ok(Ok(item)) => Ok(Json(CreateItemOutput { success: true, shopping_cart_item: item, })), @@ -151,7 +110,7 @@ async fn delete_cart_item( ) -> Result { let (token, _) = credentials.require_user(tm.into_inner()).await?; - let sc: ShoppingCart = match db + let sc: model::ShoppingCart = match db .send(database::EnsureActiveShoppingCart { buyer_id: AccountId::from(token.subject), }) @@ -203,6 +162,8 @@ pub struct CreateOrderInput { /// False if customer is allowed to be charged on site. /// Otherwise it should be true to use payment service for charging pub charge_client: bool, + /// User currency + pub currency: String, } #[post("/order")] @@ -237,6 +198,7 @@ pub(crate) async fn create_order( last_name, language, charge_client, + currency, } = payload; let ip = match req.peer_addr() { Some(ip) => ip, @@ -246,7 +208,7 @@ pub(crate) async fn create_order( let payment_manager::CreatePaymentResult { redirect_uri, .. } = query_pay!( payment, payment_manager::RequestPayment { - currency: "PLN".to_string(), + currency, buyer: payment_manager::Buyer { email, phone, @@ -274,7 +236,6 @@ pub(crate) fn configure(config: &mut ServiceConfig) { .realm("user api") .scope("customer_id role subject audience expiration_time not_before_time issued_at_time")) .service(shopping_cart) - .service(shopping_cart_items) .service(delete_cart_item) .service(create_order)); }