diff --git a/editoast/editoast_derive/src/modelv2.rs b/editoast/editoast_derive/src/modelv2.rs index 4368df9d540..e21f2facf9a 100644 --- a/editoast/editoast_derive/src/modelv2.rs +++ b/editoast/editoast_derive/src/modelv2.rs @@ -1,6 +1,7 @@ mod args; mod codegen; mod config; +mod crud; mod identifier; mod parsing; mod utils; @@ -93,6 +94,7 @@ fn test_construction() { #[model(table = editoast_models::tables::osrd_infra_document)] #[model(row(type_name = "DocumentRow", derive(Debug)))] #[model(changeset(type_name = "DocumentChangeset", public, derive(Debug)))] // fields are public + #[model(gen(ops = crud, batch_ops = crud, list))] struct Document { #[model(column = "id", preferred, primary)] id_: i64, diff --git a/editoast/editoast_derive/src/modelv2/args.rs b/editoast/editoast_derive/src/modelv2/args.rs index c17b8cf7af6..1d9479b5146 100644 --- a/editoast/editoast_derive/src/modelv2/args.rs +++ b/editoast/editoast_derive/src/modelv2/args.rs @@ -1,6 +1,6 @@ #![allow(clippy::manual_unwrap_or_default)] -use super::RawIdentifier; +use super::{crud::Crud, RawIdentifier}; use darling::{ ast, util::{self, PathList}, @@ -22,6 +22,8 @@ pub(super) struct ModelArgs { pub(super) changeset: GeneratedTypeArgs, #[darling(multiple, rename = "identifier")] pub(super) identifiers: Vec, + #[darling(rename = "gen")] + pub(super) impl_plan: ImplPlan, #[darling(default)] pub(super) preferred: Option, #[darling(default)] @@ -30,6 +32,16 @@ pub(super) struct ModelArgs { pub(super) data: ast::Data, } +#[derive(Debug, PartialEq, Eq, FromMeta)] +pub(super) struct ImplPlan { + #[darling(default)] + pub(super) ops: Crud, + #[darling(default)] + pub(super) batch_ops: Crud, + #[darling(default)] + pub(super) list: bool, +} + #[derive(FromMeta, Default, Debug, PartialEq)] pub(super) struct GeneratedTypeArgs { #[darling(default)] diff --git a/editoast/editoast_derive/src/modelv2/codegen.rs b/editoast/editoast_derive/src/modelv2/codegen.rs index 59fc69b2626..c89debe61d0 100644 --- a/editoast/editoast_derive/src/modelv2/codegen.rs +++ b/editoast/editoast_derive/src/modelv2/codegen.rs @@ -22,6 +22,7 @@ mod row_decl; mod update_batch_impl; mod update_impl; +use quote::ToTokens; use syn::parse_quote; use self::changeset_builder_impl_block::BuilderType; @@ -52,6 +53,7 @@ use self::row_decl::RowFieldDecl; use self::update_batch_impl::UpdateBatchImpl; use self::update_impl::UpdateImpl; +use super::args::ImplPlan; use super::identifier::Identifier; use super::utils::np; use super::ModelConfig; @@ -111,6 +113,24 @@ impl Identifier { } } +impl ImplPlan { + fn has_read(&self) -> bool { + self.ops.read || self.batch_ops.read + } + + fn has_create(&self) -> bool { + self.ops.create || self.batch_ops.create + } + + fn has_update(&self) -> bool { + self.ops.update || self.batch_ops.update + } + + fn has_upsert(&self) -> bool { + self.has_update() || self.has_create() + } +} + impl ModelConfig { pub(crate) fn model_impl(&self) -> ModelImpl { ModelImpl { @@ -135,11 +155,14 @@ impl ModelConfig { } } - pub(crate) fn model_field_api_impl_blocks(&self) -> Vec { + pub(crate) fn model_field_api_impl_blocks(&self) -> Vec> { self.iter_fields() - .map(|field| ModelFieldApiImplBlock { - model: self.model.clone(), - field: field.clone(), + .map(|field| { + ModelFieldApiImplBlock { + model: self.model.clone(), + field: field.clone(), + } + .tokens_if(self.impl_plan.list) }) .collect() } @@ -180,19 +203,21 @@ impl ModelConfig { } } - pub(crate) fn changeset_builder_impl_block(&self) -> ChangesetBuilderImplBlock { + pub(crate) fn changeset_builder_impl_block(&self) -> Option { ChangesetBuilderImplBlock { builder_type: BuilderType::Changeset, model: self.model.clone(), changeset: self.changeset.ident(), fields: self.changeset_fields().cloned().collect(), } + .tokens_if(self.impl_plan.has_upsert()) } - pub(crate) fn patch_builder_impl_block(&self) -> ChangesetBuilderImplBlock { - let mut builder = self.changeset_builder_impl_block(); - builder.builder_type = BuilderType::Patch; - builder + pub(crate) fn patch_builder_impl_block(&self) -> Option { + self.changeset_builder_impl_block().and_then(|mut builder| { + builder.builder_type = BuilderType::Patch; + builder.tokens_if(self.impl_plan.has_update()) + }) } pub(crate) fn identifiable_impls(&self) -> Vec { @@ -229,90 +254,106 @@ impl ModelConfig { } } - pub(crate) fn retrieve_impls(&self) -> Vec { + pub(crate) fn retrieve_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| RetrieveImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - row: self.row.ident(), - identifier: identifier.clone(), + .map(|identifier| { + RetrieveImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + row: self.row.ident(), + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.ops.read) }) .collect() } - pub(crate) fn exists_impls(&self) -> Vec { + pub(crate) fn exists_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| ExistsImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - identifier: identifier.clone(), + .map(|identifier| { + ExistsImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.has_read()) }) .collect() } - pub(crate) fn update_impls(&self) -> Vec { + pub(crate) fn update_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| UpdateImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - row: self.row.ident(), - changeset: self.changeset.ident(), - identifier: identifier.clone(), + .map(|identifier| { + UpdateImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + row: self.row.ident(), + changeset: self.changeset.ident(), + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.ops.update) }) .collect() } - pub(crate) fn delete_static_impls(&self) -> Vec { + pub(crate) fn delete_static_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| DeleteStaticImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - identifier: identifier.clone(), + .map(|identifier| { + DeleteStaticImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.ops.delete) }) .collect() } - pub(crate) fn create_impl(&self) -> CreateImpl { + pub(crate) fn create_impl(&self) -> Option { CreateImpl { model: self.model.clone(), table_mod: self.table.clone(), row: self.row.ident(), changeset: self.changeset.ident(), } + .tokens_if(self.impl_plan.ops.create) } - pub(crate) fn delete_impl(&self) -> DeleteImpl { + pub(crate) fn delete_impl(&self) -> Option { DeleteImpl { model: self.model.clone(), table_mod: self.table.clone(), primary_key: self.get_primary_field_ident(), } + .tokens_if(self.impl_plan.ops.delete) } - pub(crate) fn list_impl(&self) -> ListImpl { + pub(crate) fn list_impl(&self) -> Option { ListImpl { model: self.model.clone(), table_mod: self.table.clone(), row: self.row.ident(), } + .tokens_if(self.impl_plan.list) } - pub(crate) fn count_impl(&self) -> CountImpl { + pub(crate) fn count_impl(&self) -> Option { CountImpl { model: self.model.clone(), table_mod: self.table.clone(), } + .tokens_if(self.impl_plan.list) } - pub(crate) fn create_batch_impl(&self) -> CreateBatchImpl { + pub(crate) fn create_batch_impl(&self) -> Option { CreateBatchImpl { model: self.model.clone(), table_name: self.table_name(), @@ -322,64 +363,89 @@ impl ModelConfig { changeset: self.changeset.ident(), field_count: self.changeset_fields().count(), } + .tokens_if(self.impl_plan.batch_ops.create) } - pub(crate) fn create_batch_with_key_impls(&self) -> Vec { + pub(crate) fn create_batch_with_key_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| CreateBatchWithKeyImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - chunk_size_limit: self.batch_chunk_size_limit, - row: self.row.ident(), - changeset: self.changeset.ident(), - identifier: identifier.clone(), - field_count: self.changeset_fields().count(), + .map(|identifier| { + CreateBatchWithKeyImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + chunk_size_limit: self.batch_chunk_size_limit, + row: self.row.ident(), + changeset: self.changeset.ident(), + identifier: identifier.clone(), + field_count: self.changeset_fields().count(), + } + .tokens_if(self.impl_plan.batch_ops.create) }) .collect() } - pub(crate) fn retrieve_batch_impls(&self) -> Vec { + pub(crate) fn retrieve_batch_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| RetrieveBatchImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - chunk_size_limit: self.batch_chunk_size_limit, - row: self.row.ident(), - identifier: identifier.clone(), + .map(|identifier| { + RetrieveBatchImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + chunk_size_limit: self.batch_chunk_size_limit, + row: self.row.ident(), + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.batch_ops.read) }) .collect() } - pub(crate) fn update_batch_impls(&self) -> Vec { + pub(crate) fn update_batch_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| UpdateBatchImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - chunk_size_limit: self.batch_chunk_size_limit, - row: self.row.ident(), - changeset: self.changeset.ident(), - identifier: identifier.clone(), - primary_key_column: self.get_primary_field_column(), + .map(|identifier| { + UpdateBatchImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + chunk_size_limit: self.batch_chunk_size_limit, + row: self.row.ident(), + changeset: self.changeset.ident(), + identifier: identifier.clone(), + primary_key_column: self.get_primary_field_column(), + } + .tokens_if(self.impl_plan.batch_ops.update) }) .collect() } - pub(crate) fn delete_batch_impls(&self) -> Vec { + pub(crate) fn delete_batch_impls(&self) -> Vec> { self.identifiers .iter() - .map(|identifier| DeleteBatchImpl { - model: self.model.clone(), - table_name: self.table_name(), - table_mod: self.table.clone(), - chunk_size_limit: self.batch_chunk_size_limit, - identifier: identifier.clone(), + .map(|identifier| { + DeleteBatchImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + chunk_size_limit: self.batch_chunk_size_limit, + identifier: identifier.clone(), + } + .tokens_if(self.impl_plan.batch_ops.delete) }) .collect() } } + +trait TokensIf: Sized { + fn tokens_if(self, condition: bool) -> Option { + if condition { + Some(self) + } else { + None + } + } +} + +impl TokensIf for T {} diff --git a/editoast/editoast_derive/src/modelv2/config.rs b/editoast/editoast_derive/src/modelv2/config.rs index e905d769308..062c9f46b2a 100644 --- a/editoast/editoast_derive/src/modelv2/config.rs +++ b/editoast/editoast_derive/src/modelv2/config.rs @@ -6,7 +6,7 @@ use std::{ use syn::parse_quote; use super::{ - args::GeneratedTypeArgs, + args::{GeneratedTypeArgs, ImplPlan}, identifier::{Identifier, RawIdentifier}, }; @@ -22,6 +22,7 @@ pub(crate) struct ModelConfig { pub(crate) identifiers: HashSet, // identifiers ⊆ fields pub(crate) preferred_identifier: Identifier, // preferred_identifier ∈ identifiers pub(crate) primary_identifier: Identifier, // primary_identifier ∈ identifiers + pub(crate) impl_plan: ImplPlan, } #[derive(Debug, PartialEq, Clone)] diff --git a/editoast/editoast_derive/src/modelv2/crud.rs b/editoast/editoast_derive/src/modelv2/crud.rs new file mode 100644 index 00000000000..09b306db2fc --- /dev/null +++ b/editoast/editoast_derive/src/modelv2/crud.rs @@ -0,0 +1,117 @@ +use darling::FromMeta; +use syn::Expr; + +#[derive(Debug, Default, Clone, Copy, PartialEq, Eq)] +pub(super) struct Crud { + pub(super) create: bool, + pub(super) read: bool, + pub(super) update: bool, + pub(super) delete: bool, +} + +impl FromMeta for Crud { + fn from_expr(expr: &syn::Expr) -> darling::Result { + match expr { + Expr::Path(path) => { + let s = path + .path + .segments + .first() + .expect("a valid path has at least one segment") + .ident + .to_string() + .to_lowercase(); + if let Some(find) = s.chars().find(|c| !"crud".contains(*c)) { + return Err(darling::Error::unknown_value(&find.to_string()).with_span(path)); + } + Ok(Self { + create: s.contains('c'), + read: s.contains('r'), + update: s.contains('u'), + delete: s.contains('d'), + }) + } + _ => Err(darling::Error::unexpected_expr_type(expr)), + } + .map_err(|e| e.with_span(expr)) + } +} + +#[cfg(test)] +mod tests { + use pretty_assertions::assert_eq; + use quote::quote; + + use super::*; + + fn parse(tokens: proc_macro2::TokenStream) -> Option { + let sym: syn::Attribute = syn::parse_quote!(#[ignore = #tokens]); + FromMeta::from_meta(&sym.meta).ok() + } + + #[test] + fn full() { + assert_eq!( + parse(quote! { crud }).unwrap(), + Crud { + create: true, + read: true, + update: true, + delete: true, + } + ); + } + + #[test] + fn some() { + assert_eq!( + parse(quote! { rd }).unwrap(), + Crud { + create: false, + read: true, + update: false, + delete: true, + } + ); + } + + #[test] + fn one() { + assert_eq!( + parse(quote! { c }).unwrap(), + Crud { + create: true, + read: false, + update: false, + delete: false, + } + ); + assert_eq!( + parse(quote! { r }).unwrap(), + Crud { + create: false, + read: true, + update: false, + delete: false, + } + ); + } + + #[test] + fn duplicates() { + assert_eq!( + parse(quote! { ccrd }).unwrap(), + Crud { + create: true, + read: true, + update: false, + delete: true, + } + ); + } + + #[test] + fn invalid() { + assert!(parse(quote! { crod }).is_none()); + } +} diff --git a/editoast/editoast_derive/src/modelv2/parsing.rs b/editoast/editoast_derive/src/modelv2/parsing.rs index 0615ee289c7..b8e92eded80 100644 --- a/editoast/editoast_derive/src/modelv2/parsing.rs +++ b/editoast/editoast_derive/src/modelv2/parsing.rs @@ -4,17 +4,30 @@ use darling::Error; use proc_macro2::Span; use super::{ - args::{GeneratedTypeArgs, ModelArgs, ModelFieldArgs}, + args::{GeneratedTypeArgs, ImplPlan, ModelArgs, ModelFieldArgs}, + crud::Crud, identifier::{Identifier, RawIdentifier}, FieldTransformation, Fields, ModelConfig, ModelField, DEFAULT_BATCH_CHUNK_SIZE_LIMIT, }; +impl ImplPlan { + fn generates_something(&self) -> bool { + self.ops != Crud::default() || self.batch_ops != Crud::default() || self.list + } +} + impl ModelConfig { pub(crate) fn from_macro_args( options: ModelArgs, model_name: syn::Ident, visibility: syn::Visibility, ) -> darling::Result { + if !options.impl_plan.generates_something() { + return Err(Error::custom( + "Model: at least one operation must be generated", + )); + } + let row = GeneratedTypeArgs { type_name: options.row.type_name.or(Some(format!("{}Row", model_name))), ..options.row @@ -121,6 +134,7 @@ impl ModelConfig { batch_chunk_size_limit: options .batch_chunk_size_limit .unwrap_or(DEFAULT_BATCH_CHUNK_SIZE_LIMIT), + impl_plan: options.impl_plan, fields, row, changeset, diff --git a/editoast/src/modelsv2/documents.rs b/editoast/src/modelsv2/documents.rs index 38800ac8f0d..0ab1542152b 100644 --- a/editoast/src/modelsv2/documents.rs +++ b/editoast/src/modelsv2/documents.rs @@ -6,6 +6,7 @@ use editoast_derive::ModelV2; #[derive(Debug, Default, Clone, ModelV2)] #[model(table = editoast_models::tables::document)] +#[model(gen(ops = crd))] pub struct Document { pub id: i64, pub content_type: String, diff --git a/editoast/src/modelsv2/electrical_profiles.rs b/editoast/src/modelsv2/electrical_profiles.rs index b12d8277cdc..7d93d404709 100644 --- a/editoast/src/modelsv2/electrical_profiles.rs +++ b/editoast/src/modelsv2/electrical_profiles.rs @@ -13,6 +13,7 @@ use editoast_schemas::infra::ElectricalProfileSetData; #[derive(Clone, Debug, Serialize, Deserialize, ModelV2, ToSchema)] #[model(table = editoast_models::tables::electrical_profile_set)] #[model(changeset(derive(Deserialize)))] +#[model(gen(ops = crd))] pub struct ElectricalProfileSet { pub id: i64, pub name: String, diff --git a/editoast/src/modelsv2/infra.rs b/editoast/src/modelsv2/infra.rs index aea67efe9f6..7a4b7c84131 100644 --- a/editoast/src/modelsv2/infra.rs +++ b/editoast/src/modelsv2/infra.rs @@ -58,6 +58,7 @@ pub const DEFAULT_INFRA_VERSION: &str = "0"; #[derive(Debug, Clone, Derivative, Serialize, Deserialize, ModelV2, utoipa::ToSchema)] #[model(table = editoast_models::tables::infra)] +#[model(gen(ops = crud, batch_ops = r, list))] #[derivative(Default)] pub struct Infra { pub id: i64, diff --git a/editoast/src/modelsv2/infra_objects.rs b/editoast/src/modelsv2/infra_objects.rs index 058ca6b1c0b..f2494c84d1b 100644 --- a/editoast/src/modelsv2/infra_objects.rs +++ b/editoast/src/modelsv2/infra_objects.rs @@ -41,6 +41,7 @@ macro_rules! infra_model { #[derive(Debug, Clone, Default, Serialize, Deserialize, ModelV2)] #[model(table = $table)] #[model(preferred = (infra_id, obj_id))] + #[model(gen(ops = crud, batch_ops = crud, list))] pub struct $name { pub id: i64, pub obj_id: String, diff --git a/editoast/src/modelsv2/mod.rs b/editoast/src/modelsv2/mod.rs index f6077fcf812..71aca405c36 100644 --- a/editoast/src/modelsv2/mod.rs +++ b/editoast/src/modelsv2/mod.rs @@ -57,6 +57,7 @@ mod tests { #[derive(Debug, Default, Clone, ModelV2, PartialEq, Eq)] #[model(table = editoast_models::tables::document)] + #[model(gen(ops = crud, batch_ops = crud, list))] struct Document { id: i64, content_type: String, @@ -164,6 +165,7 @@ mod tests { #[derive(Debug, Clone, ModelV2)] #[model(table = editoast_models::tables::document)] + #[model(gen(ops = r, batch_ops = c))] struct Document { id: i64, content_type: String, diff --git a/editoast/src/modelsv2/projects.rs b/editoast/src/modelsv2/projects.rs index e19b52dc02a..ebbdf9d92c6 100644 --- a/editoast/src/modelsv2/projects.rs +++ b/editoast/src/modelsv2/projects.rs @@ -20,6 +20,7 @@ editoast_common::schemas! { #[derive(Clone, Debug, Serialize, Deserialize, ModelV2, ToSchema, PartialEq)] #[model(table = editoast_models::tables::project)] +#[model(gen(ops = crud, list))] pub struct Project { pub id: i64, pub name: String, diff --git a/editoast/src/modelsv2/rolling_stock_image.rs b/editoast/src/modelsv2/rolling_stock_image.rs index 0763654b470..88f5358c8d2 100644 --- a/editoast/src/modelsv2/rolling_stock_image.rs +++ b/editoast/src/modelsv2/rolling_stock_image.rs @@ -8,6 +8,7 @@ use serde::Serialize; #[derive(Debug, Clone, Serialize, ModelV2)] #[model(table = editoast_models::tables::rolling_stock_separate_image)] +#[model(gen(ops = c))] pub struct RollingStockSeparatedImageModel { pub id: i64, pub order: i32, diff --git a/editoast/src/modelsv2/rolling_stock_livery.rs b/editoast/src/modelsv2/rolling_stock_livery.rs index baa839190d7..624438364e6 100644 --- a/editoast/src/modelsv2/rolling_stock_livery.rs +++ b/editoast/src/modelsv2/rolling_stock_livery.rs @@ -21,9 +21,10 @@ use serde::Deserialize; /// /!\ Its compound image is not deleted by cascade if the livery is removed. /// #[derive(Debug, Clone, Derivative, ModelV2)] +#[cfg_attr(test, derive(Deserialize))] #[derivative(Default)] #[model(table = editoast_models::tables::rolling_stock_livery)] -#[cfg_attr(test, derive(Deserialize))] +#[model(gen(ops = crd, list))] pub struct RollingStockLiveryModel { pub id: i64, pub name: String, diff --git a/editoast/src/modelsv2/rolling_stock_model.rs b/editoast/src/modelsv2/rolling_stock_model.rs index 0acb461db9b..67a9cea9a40 100644 --- a/editoast/src/modelsv2/rolling_stock_model.rs +++ b/editoast/src/modelsv2/rolling_stock_model.rs @@ -34,6 +34,7 @@ editoast_common::schemas! { #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, ModelV2, ToSchema)] #[model(table = editoast_models::tables::rolling_stock)] +#[model(gen(ops = crud, batch_ops = r, list))] #[model(changeset(derive(Validate), public))] #[schema(as = RollingStock)] pub struct RollingStockModel { diff --git a/editoast/src/modelsv2/scenario.rs b/editoast/src/modelsv2/scenario.rs index 8d2f4380126..a84e2675c63 100644 --- a/editoast/src/modelsv2/scenario.rs +++ b/editoast/src/modelsv2/scenario.rs @@ -14,6 +14,7 @@ use editoast_models::DbConnection; #[derive(Debug, Clone, ModelV2, Deserialize, Serialize, ToSchema)] #[schema(as = ScenarioV2)] #[model(table = editoast_models::tables::scenario_v2)] +#[model(gen(ops = crud, list))] #[cfg_attr(test, derive(PartialEq))] pub struct Scenario { pub id: i64, diff --git a/editoast/src/modelsv2/stdcm_search_environment.rs b/editoast/src/modelsv2/stdcm_search_environment.rs index 96f973f44b3..87e4eac4879 100644 --- a/editoast/src/modelsv2/stdcm_search_environment.rs +++ b/editoast/src/modelsv2/stdcm_search_environment.rs @@ -15,6 +15,7 @@ use serde::Deserialize; #[derive(Debug, Clone, ModelV2, ToSchema, Serialize)] #[model(table = editoast_models::tables::stdcm_search_environment)] +#[model(gen(ops = crd, list))] #[cfg_attr(test, derive(Deserialize, PartialEq), model(changeset(derive(Clone))))] pub struct StdcmSearchEnvironment { pub id: i64, diff --git a/editoast/src/modelsv2/study.rs b/editoast/src/modelsv2/study.rs index 357b1f83b3e..e88da6b3623 100644 --- a/editoast/src/modelsv2/study.rs +++ b/editoast/src/modelsv2/study.rs @@ -15,6 +15,7 @@ use editoast_models::DbConnection; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ModelV2, ToSchema)] #[model(table = editoast_models::tables::study)] +#[model(gen(ops = crud, list))] pub struct Study { pub id: i64, pub name: String, diff --git a/editoast/src/modelsv2/train_schedule.rs b/editoast/src/modelsv2/train_schedule.rs index 4c5fa98f91b..dad10829c39 100644 --- a/editoast/src/modelsv2/train_schedule.rs +++ b/editoast/src/modelsv2/train_schedule.rs @@ -11,6 +11,7 @@ use editoast_schemas::train_schedule::TrainScheduleOptions; #[derive(Debug, Default, Clone, ModelV2)] #[model(table = editoast_models::tables::train_schedule_v2)] +#[model(gen(ops = crud, batch_ops = crd, list))] pub struct TrainSchedule { pub id: i64, pub train_name: String, diff --git a/editoast/src/modelsv2/work_schedules.rs b/editoast/src/modelsv2/work_schedules.rs index e8366c53007..511110103cc 100644 --- a/editoast/src/modelsv2/work_schedules.rs +++ b/editoast/src/modelsv2/work_schedules.rs @@ -9,6 +9,7 @@ use utoipa::ToSchema; #[derive(Debug, Clone, ModelV2)] #[model(table = editoast_models::tables::work_schedule_group)] +#[model(gen(ops = crd, batch_ops = c, list))] pub struct WorkScheduleGroup { pub id: i64, pub creation_date: NaiveDateTime, @@ -25,6 +26,7 @@ pub enum WorkScheduleType { #[derive(Debug, Default, Clone, ModelV2)] #[model(table = editoast_models::tables::work_schedule)] +#[model(gen(batch_ops = c, list))] pub struct WorkSchedule { pub id: i64, pub start_date_time: NaiveDateTime, diff --git a/editoast/src/views/work_schedules.rs b/editoast/src/views/work_schedules.rs index bd26c9e6680..a8fb45db891 100644 --- a/editoast/src/views/work_schedules.rs +++ b/editoast/src/views/work_schedules.rs @@ -15,13 +15,10 @@ use utoipa::ToSchema; use crate::error::InternalError; use crate::error::Result; +use crate::modelsv2::prelude::*; use crate::modelsv2::work_schedules::WorkSchedule; use crate::modelsv2::work_schedules::WorkScheduleGroup; use crate::modelsv2::work_schedules::WorkScheduleType; -use crate::modelsv2::Changeset; -use crate::modelsv2::Create; -use crate::modelsv2::CreateBatch; -use crate::modelsv2::Model; use crate::views::AuthorizationError; use crate::views::AuthorizerExt; use crate::AppState; @@ -187,7 +184,6 @@ pub mod test { use std::ops::DerefMut; use super::*; - use crate::modelsv2::prelude::*; use crate::views::test_app::TestAppBuilder; #[rstest]