diff --git a/tests/bakery_chain/bakery.rs b/tests/bakery_chain/bakery.rs index 567eaa86..ff4577c8 100644 --- a/tests/bakery_chain/bakery.rs +++ b/tests/bakery_chain/bakery.rs @@ -37,6 +37,7 @@ impl PrimaryKeyTrait for PrimaryKey { #[derive(Copy, Clone, Debug, EnumIter)] pub enum Relation { Baker, + Order, } impl ColumnTrait for Column { @@ -55,6 +56,7 @@ impl RelationTrait for Relation { fn def(&self) -> RelationDef { match self { Self::Baker => Entity::has_many(super::baker::Entity).into(), + Self::Order => Entity::has_many(super::order::Entity).into(), } } } diff --git a/tests/bakery_chain/bakery_chain_erd.jpg b/tests/bakery_chain/bakery_chain_erd.jpg index 7c9f2f91..578141d5 100644 Binary files a/tests/bakery_chain/bakery_chain_erd.jpg and b/tests/bakery_chain/bakery_chain_erd.jpg differ diff --git a/tests/bakery_chain/customer.rs b/tests/bakery_chain/customer.rs new file mode 100644 index 00000000..edbd9311 --- /dev/null +++ b/tests/bakery_chain/customer.rs @@ -0,0 +1,77 @@ +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "customer" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub name: String, + pub notes: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Name, + Notes, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Order, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Name => ColumnType::String(None).def(), + Self::Notes => ColumnType::Text.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Order => Entity::has_many(super::order::Entity) + .from(Column::Id) + .to(super::order::Column::CustomerId) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Order.def() + } +} + +impl Model { + pub fn find_orders(&self) -> Select { + Entity::find_related().belongs_to::(self) + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/tests/bakery_chain/mod.rs b/tests/bakery_chain/mod.rs index 6c1d8858..22f46f7f 100644 --- a/tests/bakery_chain/mod.rs +++ b/tests/bakery_chain/mod.rs @@ -1,2 +1,4 @@ pub mod baker; pub mod bakery; +pub mod customer; +pub mod order; diff --git a/tests/bakery_chain/order.rs b/tests/bakery_chain/order.rs new file mode 100644 index 00000000..e3218018 --- /dev/null +++ b/tests/bakery_chain/order.rs @@ -0,0 +1,88 @@ +use sea_orm::entity::prelude::*; + +#[derive(Copy, Clone, Default, Debug, DeriveEntity)] +pub struct Entity; + +impl EntityName for Entity { + fn table_name(&self) -> &str { + "order" + } +} + +#[derive(Clone, Debug, PartialEq, DeriveModel, DeriveActiveModel)] +pub struct Model { + pub id: i32, + pub total: f32, + pub bakery_id: Option, + pub customer_id: Option, + pub placed_at: String, +} + +#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)] +pub enum Column { + Id, + Total, + BakeryId, + CustomerId, + PlacedAt, +} + +#[derive(Copy, Clone, Debug, EnumIter, DerivePrimaryKey)] +pub enum PrimaryKey { + Id, +} + +impl PrimaryKeyTrait for PrimaryKey { + fn auto_increment() -> bool { + true + } +} + +#[derive(Copy, Clone, Debug, EnumIter)] +pub enum Relation { + Bakery, + Customer, +} + +impl ColumnTrait for Column { + type EntityName = Entity; + + fn def(&self) -> ColumnDef { + match self { + Self::Id => ColumnType::Integer.def(), + Self::Total => ColumnType::Money(Some((19, 4))).def(), + Self::BakeryId => ColumnType::Integer.def(), + Self::CustomerId => ColumnType::Integer.def(), + Self::PlacedAt => ColumnType::DateTime.def(), + } + } +} + +impl RelationTrait for Relation { + fn def(&self) -> RelationDef { + match self { + Self::Bakery => Entity::belongs_to(super::bakery::Entity) + .from(Column::BakeryId) + .to(super::bakery::Column::Id) + .into(), + Self::Customer => Entity::belongs_to(super::customer::Entity) + .from(Column::CustomerId) + .to(super::customer::Column::Id) + .into(), + } + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Bakery.def() + } +} + +impl Related for Entity { + fn to() -> RelationDef { + Relation::Customer.def() + } +} + +impl ActiveModelBehavior for ActiveModel {} diff --git a/tests/bakery_chain_tests.rs b/tests/bakery_chain_tests.rs index 1a2c92a0..66a7c985 100644 --- a/tests/bakery_chain_tests.rs +++ b/tests/bakery_chain_tests.rs @@ -13,11 +13,13 @@ async fn main() { } async fn setup_schema(db: &DbConn) { - assert!(create_bakery(db).await.is_ok()); - assert!(create_baker(db).await.is_ok()); + assert!(create_bakery_table(db).await.is_ok()); + assert!(create_baker_table(db).await.is_ok()); + assert!(create_customer_table(db).await.is_ok()); + assert!(create_order_table(db).await.is_ok()); } -async fn create_bakery(db: &DbConn) -> Result { +async fn create_bakery_table(db: &DbConn) -> Result { let stmt = sea_query::Table::create() .table(bakery::Entity) .if_not_exists() @@ -35,7 +37,7 @@ async fn create_bakery(db: &DbConn) -> Result { db.execute(stmt.into()).await } -async fn create_baker(db: &DbConn) -> Result { +async fn create_baker_table(db: &DbConn) -> Result { let stmt = sea_query::Table::create() .table(baker::Entity) .if_not_exists() @@ -58,5 +60,67 @@ async fn create_baker(db: &DbConn) -> Result { ) .build(SqliteQueryBuilder); - db.execute(stmt.clone().into()).await + db.execute(stmt.into()).await +} + +async fn create_customer_table(db: &DbConn) -> Result { + let stmt = sea_query::Table::create() + .table(customer::Entity) + .if_not_exists() + .col( + ColumnDef::new(customer::Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(customer::Column::Name).string()) + .col(ColumnDef::new(customer::Column::Notes).text()) + .build(SqliteQueryBuilder); + + db.execute(stmt.into()).await +} + +async fn create_order_table(db: &DbConn) -> Result { + let stmt = sea_query::Table::create() + .table(order::Entity) + .if_not_exists() + .col( + ColumnDef::new(order::Column::Id) + .integer() + .not_null() + .auto_increment() + .primary_key(), + ) + .col(ColumnDef::new(order::Column::Total).float()) + .col(ColumnDef::new(order::Column::BakeryId).integer().not_null()) + .col( + ColumnDef::new(order::Column::CustomerId) + .integer() + .not_null(), + ) + .col( + ColumnDef::new(order::Column::PlacedAt) + .date_time() + .not_null(), + ) + .foreign_key( + ForeignKey::create() + .name("FK_order_bakery") + .from(order::Entity, baker::Column::BakeryId) + .to(bakery::Entity, bakery::Column::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .foreign_key( + ForeignKey::create() + .name("FK_order_customer") + .from(order::Entity, baker::Column::BakeryId) + .to(customer::Entity, customer::Column::Id) + .on_delete(ForeignKeyAction::Cascade) + .on_update(ForeignKeyAction::Cascade), + ) + .build(SqliteQueryBuilder); + + db.execute(stmt.into()).await }