bazzar/actors/database_manager/src/orders.rs

244 lines
5.9 KiB
Rust
Raw Normal View History

2022-05-06 11:47:18 +02:00
use model::*;
use sqlx::PgPool;
2022-04-18 22:07:52 +02:00
use super::Result;
2022-05-06 11:47:18 +02:00
use crate::{
2022-05-06 16:02:38 +02:00
create_order_item, db_async_handler, shopping_cart_set_state, CreateOrderItem,
2022-05-06 11:47:18 +02:00
ShoppingCartSetState,
2022-04-20 16:09:09 +02:00
};
2022-05-22 14:19:11 +02:00
#[derive(Debug, Copy, Clone, serde::Serialize, thiserror::Error)]
#[serde(rename_all = "kebab-case", tag = "account-order")]
pub enum Error {
#[error("Can't create account order")]
CantCreate,
#[error("Can't find account order does to lack of identity")]
NoIdentity,
#[error("Account order does not exists")]
NotExists,
#[error("Failed to load all account orders")]
All,
}
#[derive(actix::Message)]
#[rtype(result = "Result<Vec<Order>>")]
pub struct AllAccountOrders;
db_async_handler!(AllAccountOrders, all_orders, Vec<Order>);
pub(crate) async fn all_orders(_msg: AllAccountOrders, pool: PgPool) -> Result<Vec<Order>> {
sqlx::query_as(
r#"
SELECT id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
FROM orders
2022-05-01 18:25:27 +02:00
ORDER BY id DESC
"#,
)
.fetch_all(&pool)
.await
.map_err(|e| {
log::error!("{e:?}");
super::Error::AccountOrder(Error::All)
})
}
2022-04-20 16:09:09 +02:00
pub mod create_order {
2022-05-06 11:47:18 +02:00
use model::{ProductId, Quantity, QuantityUnit};
2022-04-20 16:09:09 +02:00
pub struct OrderItem {
pub product_id: ProductId,
pub quantity: Quantity,
pub quantity_unit: QuantityUnit,
}
}
#[derive(actix::Message)]
#[rtype(result = "Result<Order>")]
pub struct CreateAccountOrder {
pub buyer_id: AccountId,
2022-04-20 16:09:09 +02:00
pub items: Vec<create_order::OrderItem>,
pub shopping_cart_id: ShoppingCartId,
2022-05-19 14:03:18 +02:00
pub checkout_notes: Option<String>,
}
2022-05-04 22:26:10 +02:00
db_async_handler!(
CreateAccountOrder,
create_account_order,
Order,
2022-05-04 22:26:10 +02:00
inner_create_account_order
);
2022-04-16 18:57:37 +02:00
pub(crate) async fn create_account_order(
msg: CreateAccountOrder,
2022-05-04 22:26:10 +02:00
t: &mut sqlx::Transaction<'_, sqlx::Postgres>,
) -> Result<Order> {
let order: Order = match sqlx::query_as(
r#"
INSERT INTO orders (buyer_id, status)
2022-04-18 08:22:51 +02:00
VALUES ($1, $2, $3)
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
"#,
)
.bind(msg.buyer_id)
2022-04-20 16:09:09 +02:00
.bind(OrderStatus::Confirmed)
2022-05-04 22:26:10 +02:00
.fetch_one(&mut *t)
2022-04-18 08:22:51 +02:00
.await
2022-04-20 16:09:09 +02:00
{
Ok(order) => order,
Err(e) => {
log::error!("{e:?}");
return Err(super::Error::AccountOrder(Error::CantCreate));
}
};
for item in msg.items {
if let Err(e) = create_order_item(
CreateOrderItem {
product_id: item.product_id,
order_id: order.id,
quantity: item.quantity,
quantity_unit: item.quantity_unit,
},
2022-05-04 22:26:10 +02:00
&mut *t,
2022-04-20 16:09:09 +02:00
)
.await
{
log::error!("{e:?}");
return Err(super::Error::AccountOrder(Error::CantCreate));
}
}
if let Err(e) = shopping_cart_set_state(
ShoppingCartSetState {
id: msg.shopping_cart_id,
state: ShoppingCartState::Closed,
2022-05-19 14:03:18 +02:00
checkout_notes: msg.checkout_notes,
2022-04-20 16:09:09 +02:00
},
2022-05-04 22:26:10 +02:00
t,
2022-04-20 16:09:09 +02:00
)
.await
{
2022-04-18 08:22:51 +02:00
log::error!("{e:?}");
2022-04-20 16:09:09 +02:00
return Err(super::Error::AccountOrder(Error::CantCreate));
};
Ok(order)
2022-04-18 08:22:51 +02:00
}
#[derive(actix::Message)]
#[rtype(result = "Result<Order>")]
2022-04-18 08:22:51 +02:00
pub struct UpdateAccountOrder {
pub id: OrderId,
2022-04-18 08:22:51 +02:00
pub buyer_id: AccountId,
pub status: OrderStatus,
pub order_id: Option<ExtOrderId>,
2022-04-18 08:22:51 +02:00
}
db_async_handler!(UpdateAccountOrder, update_account_order, Order);
2022-04-18 08:22:51 +02:00
pub(crate) async fn update_account_order(msg: UpdateAccountOrder, db: PgPool) -> Result<Order> {
2022-04-18 08:22:51 +02:00
sqlx::query_as(
r#"
UPDATE orders
2022-04-18 08:22:51 +02:00
SET buyer_id = $2 AND status = $3 AND order_id = $4
WHERE id = $1
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
2022-04-18 08:22:51 +02:00
"#,
)
.bind(msg.id)
.bind(msg.buyer_id)
.bind(msg.status)
.bind(msg.order_id)
.fetch_one(&db)
.await
.map_err(|e| {
log::error!("{e:?}");
super::Error::AccountOrder(Error::CantCreate)
})
}
2022-04-29 17:10:04 +02:00
#[derive(actix::Message)]
#[rtype(result = "Result<Order>")]
2022-04-29 17:10:04 +02:00
pub struct UpdateAccountOrderByExt {
pub order_ext_id: String,
pub status: OrderStatus,
}
db_async_handler!(UpdateAccountOrderByExt, update_account_order_by_ext, Order);
2022-04-29 17:10:04 +02:00
pub(crate) async fn update_account_order_by_ext(
msg: UpdateAccountOrderByExt,
db: PgPool,
) -> Result<Order> {
2022-04-29 17:10:04 +02:00
sqlx::query_as(
r#"
UPDATE orders
2022-04-29 17:10:04 +02:00
SET status = $2
WHERE order_ext_id = $1
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
2022-04-29 17:10:04 +02:00
"#,
)
.bind(msg.order_ext_id)
.bind(msg.status)
.fetch_one(&db)
.await
.map_err(|e| {
log::error!("{e:?}");
super::Error::AccountOrder(Error::CantCreate)
})
}
#[derive(actix::Message)]
#[rtype(result = "Result<Order>")]
pub struct FindAccountOrder {
pub id: OrderId,
}
db_async_handler!(FindAccountOrder, find_account_order, Order);
pub(crate) async fn find_account_order(msg: FindAccountOrder, db: PgPool) -> Result<Order> {
sqlx::query_as(
r#"
SELECT id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
FROM orders
WHERE id = $1
"#,
)
.bind(msg.id)
.fetch_one(&db)
.await
.map_err(|e| {
log::error!("{e:?}");
super::Error::AccountOrder(Error::NotExists)
})
}
2022-05-04 21:34:26 +02:00
#[derive(actix::Message)]
#[rtype(result = "Result<Order>")]
2022-05-04 21:34:26 +02:00
pub struct SetOrderServiceId {
pub id: OrderId,
2022-05-04 21:34:26 +02:00
pub service_order_id: String,
}
db_async_handler!(SetOrderServiceId, set_order_service_id, Order);
2022-05-04 21:34:26 +02:00
pub(crate) async fn set_order_service_id(msg: SetOrderServiceId, db: PgPool) -> Result<Order> {
2022-05-04 21:34:26 +02:00
sqlx::query_as(
r#"
UPDATE orders
2022-05-04 21:34:26 +02:00
SET service_order_id = $2
WHERE id = $1
RETURNING id, buyer_id, status, order_ext_id, service_order_id, checkout_notes, address_id
2022-05-04 21:34:26 +02:00
"#,
)
.bind(msg.id)
.bind(msg.service_order_id)
.fetch_one(&db)
.await
.map_err(|e| {
log::error!("{e:?}");
super::Error::AccountOrder(Error::NotExists)
})
}