From 590c43f71af93d3b70717f34764659930e50fead Mon Sep 17 00:00:00 2001 From: Leo Valais Date: Fri, 14 Jun 2024 14:27:10 +0200 Subject: [PATCH] wip --- editoast/editoast_derive/src/modelv2.rs | 1 + editoast/editoast_derive/src/modelv2/args.rs | 24 +- .../editoast_derive/src/modelv2/codegen.rs | 210 ++++++++++++------ .../editoast_derive/src/modelv2/config.rs | 7 +- editoast/editoast_derive/src/modelv2/crud.rs | 126 +++++++++++ .../editoast_derive/src/modelv2/parsing.rs | 1 + editoast/src/modelsv2/documents.rs | 1 + editoast/src/modelsv2/electrical_profiles.rs | 1 + editoast/src/modelsv2/infra.rs | 1 + editoast/src/modelsv2/light_rolling_stock.rs | 1 + editoast/src/modelsv2/projects.rs | 1 + editoast/src/modelsv2/rolling_stock_image.rs | 1 + editoast/src/modelsv2/rolling_stock_livery.rs | 1 + editoast/src/modelsv2/rolling_stock_model.rs | 1 + editoast/src/modelsv2/scenario.rs | 1 + editoast/src/modelsv2/study.rs | 1 + editoast/src/modelsv2/timetable.rs | 1 + editoast/src/modelsv2/train_schedule.rs | 1 + editoast/src/modelsv2/work_schedules.rs | 1 + editoast/src/views/work_schedules.rs | 6 +- 20 files changed, 309 insertions(+), 79 deletions(-) create mode 100644 editoast/editoast_derive/src/modelv2/crud.rs diff --git a/editoast/editoast_derive/src/modelv2.rs b/editoast/editoast_derive/src/modelv2.rs index 79bece74620..bbd7823e047 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; diff --git a/editoast/editoast_derive/src/modelv2/args.rs b/editoast/editoast_derive/src/modelv2/args.rs index 687f88e860f..3dc73a31712 100644 --- a/editoast/editoast_derive/src/modelv2/args.rs +++ b/editoast/editoast_derive/src/modelv2/args.rs @@ -1,4 +1,4 @@ -use super::RawIdentifier; +use super::{crud::Crud, RawIdentifier}; use darling::{ ast, util::{self, PathList}, @@ -20,11 +20,33 @@ pub(super) struct ModelArgs { pub(super) changeset: GeneratedTypeArgs, #[darling(multiple, rename = "identifier")] pub(super) identifiers: Vec, + #[darling(default, rename = "gen")] + pub(super) impl_plan: ImplPlan, #[darling(default)] pub(super) preferred: Option, 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, +} + +impl Default for ImplPlan { + fn default() -> Self { + ImplPlan { + ops: Crud::ALL, + batch_ops: Crud::ALL, + list: true, + } + } +} + #[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 42cd29eb66f..fe9a53b3424 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(), @@ -321,60 +362,85 @@ 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(), - 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(), + 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(), - row: self.row.ident(), - identifier: identifier.clone(), + .map(|identifier| { + RetrieveBatchImpl { + 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.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(), - 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(), + 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(), - identifier: identifier.clone(), + .map(|identifier| { + DeleteBatchImpl { + model: self.model.clone(), + table_name: self.table_name(), + table_mod: self.table.clone(), + 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 f1b6a067044..dfc6c6a153c 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}, }; @@ -21,6 +21,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)] @@ -165,3 +166,7 @@ impl ModelField { .ident } } + +impl ImplPlan { + // pub(super) fn +} diff --git a/editoast/editoast_derive/src/modelv2/crud.rs b/editoast/editoast_derive/src/modelv2/crud.rs new file mode 100644 index 00000000000..5ab967bbae6 --- /dev/null +++ b/editoast/editoast_derive/src/modelv2/crud.rs @@ -0,0 +1,126 @@ +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 Crud { + pub(super) const ALL: Self = Self { + create: true, + read: true, + update: true, + delete: true, + }; +} + +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 d4ff7f12a4d..3741371218c 100644 --- a/editoast/editoast_derive/src/modelv2/parsing.rs +++ b/editoast/editoast_derive/src/modelv2/parsing.rs @@ -118,6 +118,7 @@ impl ModelConfig { model: model_name, visibility, table: options.table, + impl_plan: options.impl_plan, fields, row, changeset, diff --git a/editoast/src/modelsv2/documents.rs b/editoast/src/modelsv2/documents.rs index 781db024975..241698eaaf5 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 = crate::tables::document)] +#[model(gen(ops = crud))] 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 8c909e6c5ad..15de237a1e9 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 = crate::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 f98a176121e..a92ba327108 100644 --- a/editoast/src/modelsv2/infra.rs +++ b/editoast/src/modelsv2/infra.rs @@ -54,6 +54,7 @@ pub const DEFAULT_INFRA_VERSION: &str = "0"; #[derive(Debug, Clone, Derivative, Serialize, Deserialize, ModelV2, utoipa::ToSchema)] #[model(table = crate::tables::infra)] +#[model(gen(ops = crud, batch_ops = r, list))] #[derivative(Default)] pub struct Infra { pub id: i64, diff --git a/editoast/src/modelsv2/light_rolling_stock.rs b/editoast/src/modelsv2/light_rolling_stock.rs index 13920e00483..7b38ccb971d 100644 --- a/editoast/src/modelsv2/light_rolling_stock.rs +++ b/editoast/src/modelsv2/light_rolling_stock.rs @@ -28,6 +28,7 @@ use crate::views::rolling_stocks::light_rolling_stock::LightRollingStock; #[derive(Debug, Clone, ModelV2, Serialize, ToSchema)] #[model(table = crate::tables::rolling_stock)] +#[model(gen(ops = r))] pub struct LightRollingStockModel { pub id: i64, pub railjson_version: String, diff --git a/editoast/src/modelsv2/projects.rs b/editoast/src/modelsv2/projects.rs index fad210dbdad..d7390cb9a74 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 = crate::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 96ea8f34c82..0603ffd4eb7 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 = crate::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 301307b2513..55e896a83fa 100644 --- a/editoast/src/modelsv2/rolling_stock_livery.rs +++ b/editoast/src/modelsv2/rolling_stock_livery.rs @@ -26,6 +26,7 @@ use crate::tables::rolling_stock_livery; #[derive(Debug, Clone, Derivative, ModelV2)] #[derivative(Default)] #[model(table = crate::tables::rolling_stock_livery)] +#[model(gen(ops = crd))] 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 6460bbf791e..36c1be309ec 100644 --- a/editoast/src/modelsv2/rolling_stock_model.rs +++ b/editoast/src/modelsv2/rolling_stock_model.rs @@ -39,6 +39,7 @@ editoast_common::schemas! { #[derive(Clone, Debug, Deserialize, Serialize, PartialEq, ModelV2, ToSchema)] #[model(table = crate::tables::rolling_stock)] +#[model(gen(ops = crud, batch_ops = r))] #[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 5b01549d3f0..776d09fba8c 100644 --- a/editoast/src/modelsv2/scenario.rs +++ b/editoast/src/modelsv2/scenario.rs @@ -14,6 +14,7 @@ use crate::modelsv2::Tags; #[derive(Debug, Clone, ModelV2, Deserialize, Serialize, ToSchema)] #[schema(as = ScenarioV2)] #[model(table = crate::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/study.rs b/editoast/src/modelsv2/study.rs index c63df41660c..fc7bdae033a 100644 --- a/editoast/src/modelsv2/study.rs +++ b/editoast/src/modelsv2/study.rs @@ -15,6 +15,7 @@ use crate::modelsv2::Scenario; #[derive(Clone, Debug, PartialEq, Serialize, Deserialize, ModelV2, ToSchema)] #[model(table = crate::tables::study)] +#[model(gen(ops = crud, list))] pub struct Study { pub id: i64, pub name: String, diff --git a/editoast/src/modelsv2/timetable.rs b/editoast/src/modelsv2/timetable.rs index 9187a49536f..8ad9a4ea22b 100644 --- a/editoast/src/modelsv2/timetable.rs +++ b/editoast/src/modelsv2/timetable.rs @@ -10,6 +10,7 @@ use crate::modelsv2::Retrieve; #[derive(Debug, Default, Clone, ModelV2)] #[model(table = crate::tables::timetable_v2)] +#[model(gen(ops = crud, list))] #[cfg_attr(test, derive(serde::Deserialize, PartialEq))] pub struct Timetable { pub id: i64, diff --git a/editoast/src/modelsv2/train_schedule.rs b/editoast/src/modelsv2/train_schedule.rs index 323755a8373..43e07b93188 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 = crate::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 9a618f83eea..45d7128c82a 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 = crate::tables::work_schedule_group)] +#[model(gen(ops = crd, batch_ops = c, list))] pub struct WorkScheduleGroup { pub id: i64, pub creation_date: NaiveDateTime, diff --git a/editoast/src/views/work_schedules.rs b/editoast/src/views/work_schedules.rs index ae374457b2f..0f074595f0e 100644 --- a/editoast/src/views/work_schedules.rs +++ b/editoast/src/views/work_schedules.rs @@ -14,14 +14,11 @@ 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::DbConnectionPool; -use crate::modelsv2::Model; use editoast_schemas::infra::TrackRange; crate::routes! { @@ -178,7 +175,6 @@ pub mod test { use super::*; use crate::assert_response_error_type_match; use crate::fixtures::tests::{db_pool, TestFixture}; - use crate::modelsv2::Retrieve; use crate::views::tests::create_test_service; async fn create_work_schedule_group_fixture(