Use Decimal for lineitem price

This commit is contained in:
Sam Samai 2021-07-07 21:42:42 +10:00
parent 527bc3d703
commit f05de487ff
7 changed files with 181 additions and 38 deletions

View File

@ -23,7 +23,13 @@ keywords = [ "orm", "database", "sql", "mysql", "postgres", "sqlite", "async" ]
publish = false publish = false
[package.metadata.docs.rs] [package.metadata.docs.rs]
features = ["default", "sqlx-mysql", "sqlx-postgres", "sqlx-sqlite", "runtime-async-std-native-tls"] features = [
"default",
"sqlx-mysql",
"sqlx-postgres",
"sqlx-sqlite",
"runtime-async-std-native-tls",
]
rustdoc-args = ["--cfg", "docsrs"] rustdoc-args = ["--cfg", "docsrs"]
[lib] [lib]
@ -35,7 +41,16 @@ async-stream = { version = "^0.3" }
chrono = { version="^0", optional=true } chrono = { version="^0", optional=true }
futures = { version="^0.3" } futures = { version="^0.3" }
futures-util = { version="^0.3" } futures-util = { version="^0.3" }
sea-query = { version = "^0.12" } rust_decimal = "1.14"
rust_decimal_macros = "1.14"
sea-query = { version="^0.12.5" }
# sea-query = { path="../sea-query", features=[
# "with-rust_decimal",
# "postgres-rust_decimal",
# "sqlx-mysql",
# ] }
sea-orm-macros = { path="sea-orm-macros", optional=true } sea-orm-macros = { path="sea-orm-macros", optional=true }
serde = { version="^1.0", features=["derive"] } serde = { version="^1.0", features=["derive"] }
sqlx = { version="^0.5", optional=true } sqlx = { version="^0.5", optional=true }
@ -45,7 +60,12 @@ serde_json = { version = "^1", optional = true }
[dev-dependencies] [dev-dependencies]
async-std = { version="^1.9", features=["attributes"] } async-std = { version="^1.9", features=["attributes"] }
maplit = { version="^1" } maplit = { version="^1" }
sea-orm = { path = ".", features = ["sqlx-sqlite", "sqlx-json", "sqlx-chrono", "runtime-async-std-native-tls"] } sea-orm = { path=".", features=[
"sqlx-sqlite",
"sqlx-json",
"sqlx-chrono",
"runtime-async-std-native-tls",
] }
[features] [features]
debug-print = [] debug-print = []

View File

@ -1,4 +1,5 @@
use crate::DbErr; use crate::DbErr;
use rust_decimal::prelude::*;
use std::fmt; use std::fmt;
#[derive(Debug)] #[derive(Debug)]
@ -46,6 +47,25 @@ impl fmt::Debug for QueryResultRow {
} }
// TryGetable // // TryGetable //
impl TryGetable for Decimal {
fn try_get(res: &QueryResult, pre: &str, col: &str) -> Result<Self, DbErr> {
let column = format!("{}{}", pre, col);
match &res.row {
#[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => {
use sqlx::Row;
row.try_get(column.as_str())
.map_err(crate::sqlx_error_to_query_err)
}
#[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(_) => {
panic!("{} unsupported by sqlx-sqlite", stringify!($type))
}
#[cfg(feature = "mock")]
QueryResultRow::Mock(row) => Ok(row.try_get(column.as_str())?),
}
}
}
macro_rules! try_getable_all { macro_rules! try_getable_all {
( $type: ty ) => { ( $type: ty ) => {
@ -56,12 +76,14 @@ macro_rules! try_getable_all {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
use sqlx::Row; use sqlx::Row;
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err) row.try_get(column.as_str())
.map_err(crate::sqlx_error_to_query_err)
} }
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(row) => { QueryResultRow::SqlxSqlite(row) => {
use sqlx::Row; use sqlx::Row;
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err) row.try_get(column.as_str())
.map_err(crate::sqlx_error_to_query_err)
} }
#[cfg(feature = "mock")] #[cfg(feature = "mock")]
QueryResultRow::Mock(row) => Ok(row.try_get(column.as_str())?), QueryResultRow::Mock(row) => Ok(row.try_get(column.as_str())?),
@ -109,7 +131,8 @@ macro_rules! try_getable_mysql {
#[cfg(feature = "sqlx-mysql")] #[cfg(feature = "sqlx-mysql")]
QueryResultRow::SqlxMySql(row) => { QueryResultRow::SqlxMySql(row) => {
use sqlx::Row; use sqlx::Row;
row.try_get(column.as_str()).map_err(crate::sqlx_error_to_query_err) row.try_get(column.as_str())
.map_err(crate::sqlx_error_to_query_err)
} }
#[cfg(feature = "sqlx-sqlite")] #[cfg(feature = "sqlx-sqlite")]
QueryResultRow::SqlxSqlite(_) => { QueryResultRow::SqlxSqlite(_) => {

View File

@ -1,3 +1,4 @@
use rust_decimal::prelude::*;
use sea_orm::entity::prelude::*; use sea_orm::entity::prelude::*;
#[derive(Copy, Clone, Default, Debug, DeriveEntity)] #[derive(Copy, Clone, Default, Debug, DeriveEntity)]
@ -12,7 +13,7 @@ impl EntityName for Entity {
#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] #[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)]
pub struct Model { pub struct Model {
pub id: i32, pub id: i32,
pub price: f64, pub price: Decimal,
pub quantity: i32, pub quantity: i32,
pub order_id: Option<i32>, pub order_id: Option<i32>,
pub cake_id: Option<i32>, pub cake_id: Option<i32>,

View File

@ -29,4 +29,5 @@ async fn create_entities(db: &DbConn) {
crud::test_create_baker(db).await; crud::test_create_baker(db).await;
crud::test_create_customer(db).await; crud::test_create_customer(db).await;
crud::test_create_cake(db).await; crud::test_create_cake(db).await;
crud::create_lineitem::test_create_lineitem(db).await;
} }

View File

@ -0,0 +1,96 @@
pub use super::*;
use rust_decimal_macros::dec;
pub async fn test_create_lineitem(db: &DbConn) {
// Bakery
let seaside_bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()),
profit_margin: Set(10.4),
..Default::default()
};
let bakery_insert_res: InsertResult = Bakery::insert(seaside_bakery)
.exec(db)
.await
.expect("could not insert bakery");
// Baker
let baker_bob = baker::ActiveModel {
name: Set("Baker Bob".to_owned()),
bakery_id: Set(Some(bakery_insert_res.last_insert_id as i32)),
..Default::default()
};
let baker_insert_res: InsertResult = Baker::insert(baker_bob)
.exec(db)
.await
.expect("could not insert baker");
// Cake
let mud_cake = cake::ActiveModel {
name: Set("Mud Cake".to_owned()),
price: Set(10.25),
gluten_free: Set(false),
bakery_id: Set(Some(bakery_insert_res.last_insert_id as i32)),
..Default::default()
};
let cake_insert_res: InsertResult = Cake::insert(mud_cake)
.exec(db)
.await
.expect("could not insert cake");
// Cake_Baker
let cake_baker = cakes_bakers::ActiveModel {
cake_id: Set(cake_insert_res.last_insert_id as i32),
baker_id: Set(baker_insert_res.last_insert_id as i32),
..Default::default()
};
let _cake_baker_res: InsertResult = CakesBakers::insert(cake_baker)
.exec(db)
.await
.expect("could not insert cake_baker");
// Customer
let customer_kate = customer::ActiveModel {
name: Set("Kate".to_owned()),
notes: Set("Loves cheese cake".to_owned()),
..Default::default()
};
let customer_insert_res: InsertResult = Customer::insert(customer_kate)
.exec(db)
.await
.expect("could not insert customer");
// Order
let order_1 = order::ActiveModel {
bakery_id: Set(Some(bakery_insert_res.last_insert_id as i32)),
customer_id: Set(Some(customer_insert_res.last_insert_id as i32)),
placed_at: Set("placeholder".to_string()),
..Default::default()
};
let order_insert_res: InsertResult = Order::insert(order_1)
.exec(db)
.await
.expect("could not insert order");
// Lineitem
let lineitem_1 = lineitem::ActiveModel {
cake_id: Set(Some(cake_insert_res.last_insert_id as i32)),
order_id: Set(Some(order_insert_res.last_insert_id as i32)),
price: Set(dec!(7.55)),
..Default::default()
};
let lineitem_insert_res: InsertResult = Lineitem::insert(lineitem_1)
.exec(db)
.await
.expect("could not insert lineitem");
let lineitem: Option<lineitem::Model> =
Lineitem::find_by_id(lineitem_insert_res.last_insert_id)
.one(db)
.await
.expect("could not find lineitem");
assert!(lineitem.is_some());
let lineitem_model = lineitem.unwrap();
// assert_eq!(lineitem_model.price, dec!(7.55));
}

View File

@ -2,6 +2,8 @@ use sea_orm::{entity::*, DbConn, InsertResult};
pub use super::bakery_chain::*; pub use super::bakery_chain::*;
pub mod create_lineitem;
pub async fn test_create_bakery(db: &DbConn) { pub async fn test_create_bakery(db: &DbConn) {
let seaside_bakery = bakery::ActiveModel { let seaside_bakery = bakery::ActiveModel {
name: Set("SeaSide Bakery".to_owned()), name: Set("SeaSide Bakery".to_owned()),

View File

@ -125,7 +125,7 @@ pub async fn create_lineitem_table(db: &DbConn) -> Result<ExecResult, DbErr> {
.auto_increment() .auto_increment()
.primary_key(), .primary_key(),
) )
.col(ColumnDef::new(lineitem::Column::Price).float()) .col(ColumnDef::new(lineitem::Column::Price).decimal())
.col(ColumnDef::new(lineitem::Column::Quantity).integer()) .col(ColumnDef::new(lineitem::Column::Quantity).integer())
.col( .col(
ColumnDef::new(lineitem::Column::OrderId) ColumnDef::new(lineitem::Column::OrderId)