Refactor shopping cart

This commit is contained in:
Adrian Woźniak 2022-05-05 13:34:04 +02:00
parent cb0e721dc0
commit cb096b600c
No known key found for this signature in database
GPG Key ID: 0012845A89C7352B
3 changed files with 91 additions and 70 deletions

View File

@ -67,3 +67,60 @@ pub struct AccountOrder {
pub order_id: Option<OrderId>, pub order_id: Option<OrderId>,
pub items: Vec<OrderItem>, pub items: Vec<OrderItem>,
} }
#[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<ShoppingCartItem>,
}
impl From<(model::ShoppingCart, Vec<model::ShoppingCartItem>)> for ShoppingCart {
fn from(
(
model::ShoppingCart {
id,
buyer_id,
payment_method,
state,
},
items,
): (model::ShoppingCart, Vec<model::ShoppingCartItem>),
) -> 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(),
}
}
}

View File

@ -80,7 +80,10 @@ impl Default for Command {
} }
} }
pub struct ConfigInfo {} #[derive(Options, Debug)]
pub struct ConfigInfo {
pub help: bool,
}
#[derive(Options, Debug)] #[derive(Options, Debug)]
pub struct GenerateHashOpts { pub struct GenerateHashOpts {

View File

@ -6,83 +6,42 @@ use actix_web_httpauth::extractors::bearer::BearerAuth;
use crate::actors::cart_manager; use crate::actors::cart_manager;
use crate::actors::cart_manager::CartManager; use crate::actors::cart_manager::CartManager;
use crate::database::Database; use crate::database::Database;
use crate::model::{ use crate::model::{api, AccountId, ProductId, Quantity, QuantityUnit, ShoppingCartItemId};
AccountId, ProductId, Quantity, QuantityUnit, ShoppingCart, ShoppingCartItem,
ShoppingCartItemId,
};
use crate::payment_manager::PaymentManager; 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::public::Error as PublicError;
use crate::routes::{RequireUser, Result}; use crate::routes::{RequireUser, Result};
use crate::token_manager::TokenManager; 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")] #[get("/shopping-cart")]
async fn shopping_cart( async fn shopping_cart(
db: Data<Addr<Database>>, db: Data<Addr<Database>>,
tm: Data<Addr<TokenManager>>, tm: Data<Addr<TokenManager>>,
credentials: BearerAuth, credentials: BearerAuth,
) -> Result<HttpResponse> { ) -> Result<Json<api::ShoppingCart>> {
let (token, _) = credentials.require_user(tm.into_inner()).await?; let (token, _) = credentials.require_user(tm.into_inner()).await?;
match db let cart: model::ShoppingCart = query_db!(
.send(database::EnsureActiveShoppingCart { db,
database::EnsureActiveShoppingCart {
buyer_id: AccountId::from(token.subject), buyer_id: AccountId::from(token.subject),
}) },
.await routes::Error::Public(PublicError::ApiV1(ApiV1Error::ShoppingCart(
{ ShoppingCartError::Ensure
Ok(Ok(cart)) => Ok(HttpResponse::Ok().json(cart)), )))
Ok(Err(e)) => { );
log::error!("{e}"); let items: Vec<model::ShoppingCartItem> = query_db!(
Err(ShoppingCartError::Ensure.into()) db,
} database::AccountShoppingCartItems {
Err(e) => {
log::error!("{e:?}");
Err(ShoppingCartError::Ensure.into())
}
}
}
#[get("/shopping-cart-items")]
async fn shopping_cart_items(
db: Data<Addr<Database>>,
tm: Data<Addr<TokenManager>>,
credentials: BearerAuth,
) -> Result<HttpResponse> {
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 {
account_id: cart.buyer_id, account_id: cart.buyer_id,
shopping_cart_id: Some(cart.id), shopping_cart_id: Some(cart.id),
}) },
.await routes::Error::Public(PublicError::ApiV1(ApiV1Error::ShoppingCart(
{ ShoppingCartError::Ensure
Ok(Ok(items)) => Ok(HttpResponse::Ok().json(items)), )))
Ok(Err(e)) => { );
log::error!("{e}"); let cart = api::ShoppingCart::from((cart, items));
Err(ShoppingCartError::Ensure.into()) Ok(Json(cart))
}
Err(e) => {
log::error!("{e:?}");
Err(ShoppingCartError::Ensure.into())
}
}
} }
#[derive(serde::Deserialize)] #[derive(serde::Deserialize)]
@ -95,7 +54,7 @@ pub struct CreateItemInput {
#[derive(serde::Serialize)] #[derive(serde::Serialize)]
pub struct CreateItemOutput { pub struct CreateItemOutput {
pub success: bool, pub success: bool,
pub shopping_cart_item: ShoppingCartItem, pub shopping_cart_item: model::ShoppingCartItem,
} }
#[post("/shopping-cart-item")] #[post("/shopping-cart-item")]
@ -104,7 +63,7 @@ async fn create_cart_item(
tm: Data<Addr<TokenManager>>, tm: Data<Addr<TokenManager>>,
credentials: BearerAuth, credentials: BearerAuth,
Json(payload): Json<CreateItemInput>, Json(payload): Json<CreateItemInput>,
) -> Result<HttpResponse> { ) -> Result<Json<CreateItemOutput>> {
let (token, _) = credentials.require_user(tm.into_inner()).await?; let (token, _) = credentials.require_user(tm.into_inner()).await?;
match cart match cart
@ -116,7 +75,7 @@ async fn create_cart_item(
}) })
.await .await
{ {
Ok(Ok(item)) => Ok(HttpResponse::Created().json(CreateItemOutput { Ok(Ok(item)) => Ok(Json(CreateItemOutput {
success: true, success: true,
shopping_cart_item: item, shopping_cart_item: item,
})), })),
@ -151,7 +110,7 @@ async fn delete_cart_item(
) -> Result<HttpResponse> { ) -> Result<HttpResponse> {
let (token, _) = credentials.require_user(tm.into_inner()).await?; let (token, _) = credentials.require_user(tm.into_inner()).await?;
let sc: ShoppingCart = match db let sc: model::ShoppingCart = match db
.send(database::EnsureActiveShoppingCart { .send(database::EnsureActiveShoppingCart {
buyer_id: AccountId::from(token.subject), buyer_id: AccountId::from(token.subject),
}) })
@ -203,6 +162,8 @@ pub struct CreateOrderInput {
/// False if customer is allowed to be charged on site. /// False if customer is allowed to be charged on site.
/// Otherwise it should be true to use payment service for charging /// Otherwise it should be true to use payment service for charging
pub charge_client: bool, pub charge_client: bool,
/// User currency
pub currency: String,
} }
#[post("/order")] #[post("/order")]
@ -237,6 +198,7 @@ pub(crate) async fn create_order(
last_name, last_name,
language, language,
charge_client, charge_client,
currency,
} = payload; } = payload;
let ip = match req.peer_addr() { let ip = match req.peer_addr() {
Some(ip) => ip, Some(ip) => ip,
@ -246,7 +208,7 @@ pub(crate) async fn create_order(
let payment_manager::CreatePaymentResult { redirect_uri, .. } = query_pay!( let payment_manager::CreatePaymentResult { redirect_uri, .. } = query_pay!(
payment, payment,
payment_manager::RequestPayment { payment_manager::RequestPayment {
currency: "PLN".to_string(), currency,
buyer: payment_manager::Buyer { buyer: payment_manager::Buyer {
email, email,
phone, phone,
@ -274,7 +236,6 @@ pub(crate) fn configure(config: &mut ServiceConfig) {
.realm("user api") .realm("user api")
.scope("customer_id role subject audience expiration_time not_before_time issued_at_time")) .scope("customer_id role subject audience expiration_time not_before_time issued_at_time"))
.service(shopping_cart) .service(shopping_cart)
.service(shopping_cart_items)
.service(delete_cart_item) .service(delete_cart_item)
.service(create_order)); .service(create_order));
} }