@@ -5,7 +5,7 @@ use editoast_derive::ModelV2;
5
5
use serde_derive:: { Deserialize , Serialize } ;
6
6
use utoipa:: ToSchema ;
7
7
8
- #[ derive( Debug , Default , Clone , ModelV2 ) ]
8
+ #[ derive( Debug , Default , Clone , ModelV2 , Deserialize , Serialize ) ]
9
9
#[ model( changeset( derive( Deserialize ) ) ) ]
10
10
#[ model( table = crate :: tables:: scenariov2) ]
11
11
pub struct ScenarioV2 {
@@ -19,232 +19,3 @@ pub struct ScenarioV2 {
19
19
pub timetable_id : i64 ,
20
20
pub study_id : i64 ,
21
21
}
22
-
23
- crate :: schemas! {
24
- ScenarioV2WithCountTrains
25
- }
26
-
27
- #[ derive( Debug , Clone , Deserialize , Serialize , QueryableByName , ToSchema ) ]
28
- pub struct ScenarioWithDetails {
29
- pub id : i64 ,
30
- pub infra_id : i64 ,
31
- pub name : String ,
32
- pub description : String ,
33
- pub creation_date : NaiveDateTime ,
34
- pub last_modification : NaiveDateTime ,
35
- pub tags : Vec < Option < String > > ,
36
- pub timetable_id : i64 ,
37
- pub study_id : i64 ,
38
- #[ diesel( sql_type = Text ) ]
39
- pub infra_name : String ,
40
- #[ diesel( sql_type = Nullable <Text >) ]
41
- pub electrical_profile_set_name : Option < String > ,
42
- #[ diesel( sql_type = Array <LightTrainSchedule >) ]
43
- pub train_schedules : Vec < LightTrainSchedule > ,
44
- #[ diesel( sql_type = BigInt ) ]
45
- pub trains_count : i64 ,
46
- }
47
-
48
- #[ derive( Debug , Clone , Serialize , QueryableByName , ToSchema ) ]
49
- pub struct ScenarioV2WithCountTrains {
50
- pub id : i64 ,
51
- pub infra_id : i64 ,
52
- pub name : String ,
53
- pub description : String ,
54
- pub creation_date : NaiveDateTime ,
55
- pub last_modification : NaiveDateTime ,
56
- pub tags : Vec < Option < String > > ,
57
- pub timetable_id : i64 ,
58
- pub study_id : i64 ,
59
- #[ diesel( sql_type = BigInt ) ]
60
- pub trains_count : i64 ,
61
- #[ diesel( sql_type = Text ) ]
62
- pub infra_name : String ,
63
- }
64
-
65
- impl ScenarioV2 {
66
- pub async fn with_details ( self , db_pool : Data < DbPool > ) -> Result < ScenarioWithDetails > {
67
- let mut conn = db_pool. get ( ) . await ?;
68
- self . with_details_conn ( & mut conn) . await
69
- }
70
-
71
- pub async fn with_details_conn ( self , conn : & mut PgConnection ) -> Result < ScenarioWithDetails > {
72
- use crate :: tables:: electrical_profile_set:: dsl as elec_dsl;
73
- use crate :: tables:: infra:: dsl as infra_dsl;
74
- use crate :: tables:: train_schedule:: dsl:: * ;
75
-
76
- let infra_name = infra_dsl:: infra
77
- . filter ( infra_dsl:: id. eq ( self . infra_id . unwrap ( ) ) )
78
- . select ( infra_dsl:: name)
79
- . first :: < String > ( conn)
80
- . await ?;
81
-
82
- let electrical_profile_set_name = match self . electrical_profile_set_id . unwrap ( ) {
83
- Some ( electrical_profile_set) => Some (
84
- elec_dsl:: electrical_profile_set
85
- . filter ( elec_dsl:: id. eq ( electrical_profile_set) )
86
- . select ( elec_dsl:: name)
87
- . first :: < String > ( conn)
88
- . await ?,
89
- ) ,
90
- None => None ,
91
- } ;
92
-
93
- let train_schedules = train_schedule
94
- . filter ( timetable_id. eq ( self . timetable_id . unwrap ( ) ) )
95
- . select ( ( id, train_name, departure_time, path_id) )
96
- . load :: < LightTrainSchedule > ( conn)
97
- . await ?;
98
-
99
- let trains_count = train_schedules. len ( ) as i64 ;
100
-
101
- Ok ( ScenarioWithDetails {
102
- scenario : self ,
103
- infra_name,
104
- electrical_profile_set_name,
105
- train_schedules,
106
- trains_count,
107
- } )
108
- }
109
- }
110
-
111
- /// Delete a scenario.
112
- /// When we delete a scenario, the associated timetable is deleted too.
113
- #[ async_trait]
114
- impl Delete for Scenario {
115
- async fn delete_conn ( conn : & mut PgConnection , scenario_id : i64 ) -> Result < bool > {
116
- use crate :: tables:: scenario:: dsl as scenario_dsl;
117
- use crate :: tables:: timetable:: dsl as timetable_dsl;
118
-
119
- // Delete scenario
120
- let scenario = match delete ( scenario_dsl:: scenario. filter ( scenario_dsl:: id. eq ( scenario_id) ) )
121
- . get_result :: < Scenario > ( conn)
122
- . await
123
- {
124
- Ok ( scenario) => scenario,
125
- Err ( DieselError :: NotFound ) => return Ok ( false ) ,
126
- Err ( err) => return Err ( err. into ( ) ) ,
127
- } ;
128
-
129
- // Delete timetable
130
- delete (
131
- timetable_dsl:: timetable. filter ( timetable_dsl:: id. eq ( scenario. timetable_id . unwrap ( ) ) ) ,
132
- )
133
- . execute ( conn)
134
- . await ?;
135
- Ok ( true )
136
- }
137
- }
138
-
139
- #[ async_trait]
140
- impl List < ( i64 , Ordering ) > for ScenarioWithCountTrains {
141
- /// List all scenarios with the number of trains.
142
- /// This functions takes a study_id to filter scenarios.
143
- async fn list_conn (
144
- conn : & mut PgConnection ,
145
- page : i64 ,
146
- page_size : i64 ,
147
- params : ( i64 , Ordering ) ,
148
- ) -> Result < PaginatedResponse < Self > > {
149
- let study_id = params. 0 ;
150
- let ordering = params. 1 . to_sql ( ) ;
151
- sql_query ( format ! ( "WITH scenarios_with_train_counts AS (
152
- SELECT t.*, COUNT(train_schedule.id) as trains_count
153
- FROM scenario as t
154
- LEFT JOIN train_schedule ON t.timetable_id = train_schedule.timetable_id WHERE t.study_id = $1
155
- GROUP BY t.id ORDER BY {ordering}
156
- )
157
- SELECT scenarios_with_train_counts.*, infra.name as infra_name
158
- FROM scenarios_with_train_counts
159
- JOIN infra ON infra.id = infra_id" ) )
160
- . bind :: < BigInt , _ > ( study_id)
161
- . paginate ( page, page_size)
162
- . load_and_count ( conn) . await
163
- }
164
- }
165
-
166
- #[ cfg( test) ]
167
- pub mod test {
168
- use super :: * ;
169
- use crate :: fixtures:: tests:: { db_pool, scenario_fixture_set, ScenarioFixtureSet , TestFixture } ;
170
- use crate :: models:: Delete ;
171
- use crate :: models:: List ;
172
- use crate :: models:: Ordering ;
173
- use crate :: models:: Retrieve ;
174
- use crate :: models:: Timetable ;
175
- use rstest:: rstest;
176
-
177
- #[ rstest]
178
- async fn create_delete_scenario ( db_pool : Data < DbPool > ) {
179
- let ScenarioFixtureSet { scenario, .. } = scenario_fixture_set ( ) . await ;
180
-
181
- // Delete the scenario
182
- Scenario :: delete ( db_pool. clone ( ) , scenario. id ( ) )
183
- . await
184
- . unwrap ( ) ;
185
-
186
- // Second delete should fail
187
- assert ! ( !Scenario :: delete( db_pool. clone( ) , scenario. id( ) )
188
- . await
189
- . unwrap( ) ) ;
190
- }
191
-
192
- #[ rstest]
193
- async fn get_study ( db_pool : Data < DbPool > ) {
194
- let ScenarioFixtureSet { study, .. } = scenario_fixture_set ( ) . await ;
195
-
196
- // Get a scenario
197
- assert ! ( Scenario :: retrieve( db_pool. clone( ) , study. id( ) )
198
- . await
199
- . is_ok( ) ) ;
200
- assert ! ( ScenarioWithCountTrains :: list(
201
- db_pool. clone( ) ,
202
- 1 ,
203
- 25 ,
204
- ( study. id( ) , Ordering :: LastModifiedAsc )
205
- )
206
- . await
207
- . is_ok( ) ) ;
208
- }
209
-
210
- #[ rstest]
211
- async fn sort_scenario ( db_pool : Data < DbPool > ) {
212
- let ScenarioFixtureSet {
213
- scenario,
214
- study,
215
- timetable,
216
- ..
217
- } = scenario_fixture_set ( ) . await ;
218
-
219
- // Create second timetable
220
- let timetable_2 = TestFixture :: create_legacy (
221
- Timetable {
222
- id : None ,
223
- name : Some ( timetable. model . name . clone ( ) . unwrap ( ) + "_bis" ) ,
224
- } ,
225
- db_pool. clone ( ) ,
226
- )
227
- . await ;
228
-
229
- // Create second scenario
230
- let scenario_2 = Scenario {
231
- name : Some ( scenario. model . name . clone ( ) . unwrap ( ) + "_bis" ) ,
232
- id : None ,
233
- timetable_id : Some ( timetable_2. id ( ) ) ,
234
- ..scenario. model . clone ( )
235
- } ;
236
- let _scenario_2 = TestFixture :: create_legacy ( scenario_2, db_pool. clone ( ) ) ;
237
-
238
- let scenarios =
239
- ScenarioWithCountTrains :: list ( db_pool. clone ( ) , 1 , 25 , ( study. id ( ) , Ordering :: NameDesc ) )
240
- . await
241
- . unwrap ( )
242
- . results ;
243
-
244
- for ( p1, p2) in scenarios. iter ( ) . zip ( scenarios. iter ( ) . skip ( 1 ) ) {
245
- let name_1 = p1. scenario . name . as_ref ( ) . unwrap ( ) . to_lowercase ( ) ;
246
- let name_2 = p2. scenario . name . as_ref ( ) . unwrap ( ) . to_lowercase ( ) ;
247
- assert ! ( name_1. ge( & name_2) ) ;
248
- }
249
- }
250
- }
0 commit comments