2022-04-16 06:58:48 +02:00
|
|
|
use sqlx::PgPool;
|
|
|
|
|
2022-04-18 22:07:52 +02:00
|
|
|
use super::Result;
|
2022-04-20 16:09:09 +02:00
|
|
|
use crate::database::{
|
|
|
|
create_order_item, shopping_cart_set_state, CreateOrderItem, Database, ShoppingCartSetState,
|
|
|
|
};
|
2022-04-18 22:07:52 +02:00
|
|
|
use crate::db_async_handler;
|
2022-04-16 06:58:48 +02:00
|
|
|
use crate::model::*;
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
pub enum Error {
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Can't create account order")]
|
2022-04-16 06:58:48 +02:00
|
|
|
CantCreate,
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Can't find account order does to lack of identity")]
|
2022-04-16 06:58:48 +02:00
|
|
|
NoIdentity,
|
|
|
|
#[error("Account order does not exists")]
|
|
|
|
NotExists,
|
2022-04-16 07:31:19 +02:00
|
|
|
#[error("Failed to load all account orders")]
|
2022-04-16 06:58:48 +02:00
|
|
|
All,
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<Vec<AccountOrder>>")]
|
|
|
|
pub struct AllAccountOrders;
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(AllAccountOrders, all_account_orders, Vec<AccountOrder>);
|
2022-04-16 06:58:48 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn all_account_orders(
|
|
|
|
_msg: AllAccountOrders,
|
|
|
|
pool: PgPool,
|
|
|
|
) -> Result<Vec<AccountOrder>> {
|
2022-04-16 06:58:48 +02:00
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
2022-04-29 17:10:04 +02:00
|
|
|
SELECT id, buyer_id, status, order_id, order_ext_id
|
2022-04-16 06:58:48 +02:00
|
|
|
FROM account_orders
|
2022-05-01 18:25:27 +02:00
|
|
|
ORDER BY id DESC
|
2022-04-16 06:58:48 +02:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.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 {
|
|
|
|
use crate::model::{ProductId, Quantity, QuantityUnit};
|
|
|
|
|
|
|
|
pub struct OrderItem {
|
|
|
|
pub product_id: ProductId,
|
|
|
|
pub quantity: Quantity,
|
|
|
|
pub quantity_unit: QuantityUnit,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-04-16 06:58:48 +02:00
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<AccountOrder>")]
|
|
|
|
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-04-16 06:58:48 +02:00
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(CreateAccountOrder, create_account_order, AccountOrder);
|
2022-04-16 06:58:48 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn create_account_order(
|
|
|
|
msg: CreateAccountOrder,
|
|
|
|
db: PgPool,
|
|
|
|
) -> Result<AccountOrder> {
|
2022-04-20 16:09:09 +02:00
|
|
|
let mut t = db.begin().await?;
|
|
|
|
|
|
|
|
let order: AccountOrder = match sqlx::query_as(
|
2022-04-16 06:58:48 +02:00
|
|
|
r#"
|
2022-04-20 16:09:09 +02:00
|
|
|
INSERT INTO account_orders (buyer_id, status)
|
2022-04-18 08:22:51 +02:00
|
|
|
VALUES ($1, $2, $3)
|
2022-04-29 17:10:04 +02:00
|
|
|
RETURNING id, buyer_id, status, order_ext_id
|
2022-04-16 06:58:48 +02:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.buyer_id)
|
2022-04-20 16:09:09 +02:00
|
|
|
.bind(OrderStatus::Confirmed)
|
|
|
|
.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:?}");
|
|
|
|
t.rollback().await.ok();
|
|
|
|
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,
|
|
|
|
},
|
|
|
|
&mut t,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
{
|
|
|
|
log::error!("{e:?}");
|
|
|
|
|
|
|
|
t.rollback().await.ok();
|
|
|
|
return Err(super::Error::AccountOrder(Error::CantCreate));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if let Err(e) = shopping_cart_set_state(
|
|
|
|
ShoppingCartSetState {
|
|
|
|
id: msg.shopping_cart_id,
|
|
|
|
state: ShoppingCartState::Closed,
|
|
|
|
},
|
|
|
|
&mut t,
|
|
|
|
)
|
|
|
|
.await
|
|
|
|
{
|
2022-04-18 08:22:51 +02:00
|
|
|
log::error!("{e:?}");
|
2022-04-20 16:09:09 +02:00
|
|
|
|
|
|
|
t.rollback().await.ok();
|
|
|
|
return Err(super::Error::AccountOrder(Error::CantCreate));
|
|
|
|
};
|
|
|
|
|
|
|
|
t.commit().await.ok();
|
|
|
|
|
|
|
|
Ok(order)
|
2022-04-18 08:22:51 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<AccountOrder>")]
|
|
|
|
pub struct UpdateAccountOrder {
|
|
|
|
pub id: AccountOrderId,
|
|
|
|
pub buyer_id: AccountId,
|
|
|
|
pub status: OrderStatus,
|
|
|
|
pub order_id: Option<OrderId>,
|
|
|
|
}
|
|
|
|
|
|
|
|
db_async_handler!(UpdateAccountOrder, update_account_order, AccountOrder);
|
|
|
|
|
|
|
|
pub(crate) async fn update_account_order(
|
|
|
|
msg: UpdateAccountOrder,
|
|
|
|
db: PgPool,
|
|
|
|
) -> Result<AccountOrder> {
|
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
|
|
|
UPDATE account_orders
|
|
|
|
SET buyer_id = $2 AND status = $3 AND order_id = $4
|
|
|
|
WHERE id = $1
|
2022-04-29 17:10:04 +02:00
|
|
|
RETURNING id, buyer_id, status, order_id, order_ext_id
|
2022-04-18 08:22:51 +02:00
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.id)
|
|
|
|
.bind(msg.buyer_id)
|
|
|
|
.bind(msg.status)
|
|
|
|
.bind(msg.order_id)
|
2022-04-16 06:58:48 +02:00
|
|
|
.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<AccountOrder>")]
|
|
|
|
pub struct UpdateAccountOrderByExt {
|
|
|
|
pub order_ext_id: String,
|
|
|
|
pub status: OrderStatus,
|
|
|
|
}
|
|
|
|
|
|
|
|
db_async_handler!(
|
|
|
|
UpdateAccountOrderByExt,
|
|
|
|
update_account_order_by_ext,
|
|
|
|
AccountOrder
|
|
|
|
);
|
|
|
|
|
|
|
|
pub(crate) async fn update_account_order_by_ext(
|
|
|
|
msg: UpdateAccountOrderByExt,
|
|
|
|
db: PgPool,
|
|
|
|
) -> Result<AccountOrder> {
|
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
|
|
|
UPDATE account_orders
|
|
|
|
SET status = $2
|
|
|
|
WHERE order_ext_id = $1
|
|
|
|
RETURNING id, buyer_id, status, order_id, order_ext_id
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.order_ext_id)
|
|
|
|
.bind(msg.status)
|
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::AccountOrder(Error::CantCreate)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2022-04-16 06:58:48 +02:00
|
|
|
#[derive(actix::Message)]
|
|
|
|
#[rtype(result = "Result<AccountOrder>")]
|
|
|
|
pub struct FindAccountOrder {
|
|
|
|
pub id: AccountOrderId,
|
|
|
|
}
|
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
db_async_handler!(FindAccountOrder, find_account_order, AccountOrder);
|
2022-04-16 06:58:48 +02:00
|
|
|
|
2022-04-16 18:57:37 +02:00
|
|
|
pub(crate) async fn find_account_order(msg: FindAccountOrder, db: PgPool) -> Result<AccountOrder> {
|
2022-04-16 06:58:48 +02:00
|
|
|
sqlx::query_as(
|
|
|
|
r#"
|
2022-04-29 17:10:04 +02:00
|
|
|
SELECT id, buyer_id, status, order_id, order_ext_id
|
2022-04-16 06:58:48 +02:00
|
|
|
FROM account_orders
|
|
|
|
WHERE id = $1
|
|
|
|
"#,
|
|
|
|
)
|
|
|
|
.bind(msg.id)
|
|
|
|
.fetch_one(&db)
|
|
|
|
.await
|
|
|
|
.map_err(|e| {
|
|
|
|
log::error!("{e:?}");
|
|
|
|
super::Error::AccountOrder(Error::NotExists)
|
|
|
|
})
|
|
|
|
}
|