Test multiple sequential operations
This commit is contained in:
parent
3bd9948f8c
commit
09f344ecbb
@ -1 +1 @@
|
||||
<mxfile host="Electron" modified="2021-07-21T05:22:07.657Z" agent="5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.6.13 Chrome/89.0.4389.128 Electron/12.0.7 Safari/537.36" etag="5jLKOls5fzG59mgptn88" version="14.6.13" type="device"><diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1">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</diagram></mxfile>
|
||||
<mxfile host="Electron" modified="2021-07-24T10:17:39.768Z" agent="5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) draw.io/14.6.13 Chrome/89.0.4389.128 Electron/12.0.7 Safari/537.36" etag="-nL14gemvUpu6Q8vDMJo" version="14.6.13" type="device"><diagram id="R2lEEEUBdFMjLlhIrx00" name="Page-1">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</diagram></mxfile>
|
Binary file not shown.
Before Width: | Height: | Size: 53 KiB After Width: | Height: | Size: 52 KiB |
268
tests/sequential_op_tests.rs
Normal file
268
tests/sequential_op_tests.rs
Normal file
@ -0,0 +1,268 @@
|
||||
use chrono::offset::Utc;
|
||||
use rust_decimal::prelude::*;
|
||||
use rust_decimal_macros::dec;
|
||||
use sea_orm::{entity::*, query::*, DatabaseConnection, FromQueryResult};
|
||||
use uuid::Uuid;
|
||||
|
||||
pub mod common;
|
||||
pub use common::{bakery_chain::*, setup::*, TestContext};
|
||||
|
||||
#[async_std::test]
|
||||
pub async fn test_multiple_operations() {
|
||||
let ctx = TestContext::new("mysql://root:@localhost", "multiple_sequential_operations").await;
|
||||
|
||||
init_setup(&ctx.db).await;
|
||||
let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap();
|
||||
assert_eq!(baker_least_sales.name, "Baker 2");
|
||||
|
||||
let new_cake = create_cake(&ctx.db, baker_least_sales).await.unwrap();
|
||||
create_order(&ctx.db, new_cake).await;
|
||||
|
||||
let baker_least_sales = find_baker_least_sales(&ctx.db).await.unwrap();
|
||||
assert_eq!(baker_least_sales.name, "Baker 1");
|
||||
}
|
||||
|
||||
async fn init_setup(db: &DatabaseConnection) {
|
||||
let bakery = bakery::ActiveModel {
|
||||
name: Set("SeaSide Bakery".to_owned()),
|
||||
profit_margin: Set(10.4),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert bakery");
|
||||
|
||||
let baker_1 = baker::ActiveModel {
|
||||
name: Set("Baker 1".to_owned()),
|
||||
contact_details: Set(serde_json::json!({})),
|
||||
bakery_id: Set(Some(bakery.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert baker");
|
||||
|
||||
let _baker_2 = baker::ActiveModel {
|
||||
name: Set("Baker 2".to_owned()),
|
||||
contact_details: Set(serde_json::json!({})),
|
||||
bakery_id: Set(Some(bakery.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert baker");
|
||||
|
||||
let mud_cake = cake::ActiveModel {
|
||||
name: Set("Mud Cake".to_owned()),
|
||||
price: Set(dec!(10.25)),
|
||||
gluten_free: Set(false),
|
||||
serial: Set(Uuid::new_v4()),
|
||||
bakery_id: Set(Some(bakery.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let cake_insert_res: InsertResult = Cake::insert(mud_cake)
|
||||
.exec(db)
|
||||
.await
|
||||
.expect("could not insert cake");
|
||||
|
||||
let cake_baker = cakes_bakers::ActiveModel {
|
||||
cake_id: Set(cake_insert_res.last_insert_id as i32),
|
||||
baker_id: Set(baker_1.id.clone().unwrap()),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let _cake_baker_res: InsertResult = CakesBakers::insert(cake_baker)
|
||||
.exec(db)
|
||||
.await
|
||||
.expect("could not insert cake_baker");
|
||||
|
||||
let customer_kate = customer::ActiveModel {
|
||||
name: Set("Kate".to_owned()),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert customer");
|
||||
|
||||
let kate_order_1 = order::ActiveModel {
|
||||
bakery_id: Set(Some(bakery.id.clone().unwrap())),
|
||||
customer_id: Set(Some(customer_kate.id.clone().unwrap())),
|
||||
total: Set(dec!(99.95)),
|
||||
placed_at: Set(Utc::now().naive_utc()),
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert order");
|
||||
|
||||
let _lineitem = lineitem::ActiveModel {
|
||||
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)),
|
||||
price: Set(dec!(10.00)),
|
||||
quantity: Set(12),
|
||||
order_id: Set(Some(kate_order_1.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert order");
|
||||
|
||||
let _lineitem2 = lineitem::ActiveModel {
|
||||
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)),
|
||||
price: Set(dec!(50.00)),
|
||||
quantity: Set(2),
|
||||
order_id: Set(Some(kate_order_1.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert order");
|
||||
}
|
||||
|
||||
async fn find_baker_least_sales(db: &DatabaseConnection) -> Option<baker::Model> {
|
||||
#[derive(Debug, FromQueryResult)]
|
||||
struct SelectResult {
|
||||
id: i32,
|
||||
cakes_sold_opt: Option<Decimal>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
struct LeastSalesBakerResult {
|
||||
id: i32,
|
||||
cakes_sold: Decimal,
|
||||
}
|
||||
|
||||
let rel: RelationDef = cakes_bakers::Entity::belongs_to(baker::Entity)
|
||||
.from(cakes_bakers::Column::BakerId)
|
||||
.to(baker::Column::Id)
|
||||
.into();
|
||||
|
||||
let rel2: RelationDef = cakes_bakers::Entity::belongs_to(cake::Entity)
|
||||
.from(cakes_bakers::Column::CakeId)
|
||||
.to(cake::Column::Id)
|
||||
.into();
|
||||
|
||||
let rel3: RelationDef = cake::Entity::has_many(lineitem::Entity)
|
||||
.from(cake::Column::Id)
|
||||
.to(lineitem::Column::CakeId)
|
||||
.into();
|
||||
|
||||
let select = cakes_bakers::Entity::find()
|
||||
.join(JoinType::RightJoin, rel)
|
||||
.join(JoinType::LeftJoin, rel2)
|
||||
.join(JoinType::LeftJoin, rel3)
|
||||
.select_only()
|
||||
.column(baker::Column::Id)
|
||||
.column_as(lineitem::Column::Quantity.sum(), "cakes_sold_opt")
|
||||
.group_by(baker::Column::Id);
|
||||
|
||||
let mut results: Vec<LeastSalesBakerResult> = select
|
||||
.into_model::<SelectResult>()
|
||||
.all(&db)
|
||||
.await
|
||||
.unwrap()
|
||||
.into_iter()
|
||||
.map(|b| LeastSalesBakerResult {
|
||||
id: b.id.clone(),
|
||||
cakes_sold: b.cakes_sold_opt.unwrap_or(dec!(0)),
|
||||
})
|
||||
.collect();
|
||||
|
||||
results.sort_by(|a, b| b.cakes_sold.cmp(&a.cakes_sold));
|
||||
|
||||
Baker::find_by_id(results.last().unwrap().id)
|
||||
.one(db)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn create_cake(db: &DatabaseConnection, baker: baker::Model) -> Option<cake::Model> {
|
||||
let new_cake = cake::ActiveModel {
|
||||
name: Set("New Cake".to_owned()),
|
||||
price: Set(dec!(8.00)),
|
||||
gluten_free: Set(false),
|
||||
serial: Set(Uuid::new_v4()),
|
||||
bakery_id: Set(Some(baker.bakery_id.clone().unwrap())),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let cake_insert_res: InsertResult = Cake::insert(new_cake)
|
||||
.exec(db)
|
||||
.await
|
||||
.expect("could not insert cake");
|
||||
|
||||
let cake_baker = cakes_bakers::ActiveModel {
|
||||
cake_id: Set(cake_insert_res.last_insert_id as i32),
|
||||
baker_id: Set(baker.id),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
let _cake_baker_res: InsertResult = CakesBakers::insert(cake_baker)
|
||||
.exec(db)
|
||||
.await
|
||||
.expect("could not insert cake_baker");
|
||||
|
||||
Cake::find_by_id(cake_insert_res.last_insert_id)
|
||||
.one(db)
|
||||
.await
|
||||
.unwrap()
|
||||
}
|
||||
|
||||
async fn create_order(db: &DatabaseConnection, cake: cake::Model) {
|
||||
let another_customer = customer::ActiveModel {
|
||||
name: Set("John".to_owned()),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert customer");
|
||||
|
||||
let order = order::ActiveModel {
|
||||
bakery_id: Set(Some(cake.bakery_id.unwrap())),
|
||||
customer_id: Set(Some(another_customer.id.clone().unwrap())),
|
||||
total: Set(dec!(200.00)),
|
||||
placed_at: Set(Utc::now().naive_utc()),
|
||||
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert order");
|
||||
|
||||
let _lineitem = lineitem::ActiveModel {
|
||||
cake_id: Set(Some(cake.id)),
|
||||
price: Set(dec!(10.00)),
|
||||
quantity: Set(300),
|
||||
order_id: Set(Some(order.id.clone().unwrap())),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert order");
|
||||
}
|
||||
|
||||
pub async fn test_delete_bakery(db: &DatabaseConnection) {
|
||||
let initial_bakeries = Bakery::find().all(db).await.unwrap().len();
|
||||
|
||||
let bakery = bakery::ActiveModel {
|
||||
name: Set("SeaSide Bakery".to_owned()),
|
||||
profit_margin: Set(10.4),
|
||||
..Default::default()
|
||||
}
|
||||
.save(db)
|
||||
.await
|
||||
.expect("could not insert bakery");
|
||||
|
||||
assert_eq!(
|
||||
Bakery::find().all(db).await.unwrap().len(),
|
||||
initial_bakeries + 1
|
||||
);
|
||||
|
||||
let _result = bakery.delete(db).await.expect("failed to delete bakery");
|
||||
|
||||
assert_eq!(
|
||||
Bakery::find().all(db).await.unwrap().len(),
|
||||
initial_bakeries
|
||||
);
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user