1
- use actix_web:: web:: Data ;
1
+ use crate :: error:: Result ;
2
+ use crate :: models:: List ;
3
+ use crate :: models:: Ordering ;
4
+ use crate :: modelsv2:: Model ;
5
+ use crate :: modelsv2:: Row ;
6
+ use crate :: views:: pagination:: Paginate ;
7
+ use crate :: views:: pagination:: PaginatedResponse ;
8
+ use crate :: views:: v2:: scenariov2:: ScenarioV2WithCountTrains ;
9
+ use async_trait:: async_trait;
2
10
use chrono:: NaiveDateTime ;
3
- use diesel:: sql_types:: { BigInt , Text } ;
11
+ use diesel:: sql_query;
12
+ use diesel:: sql_types:: { Array , BigInt , Text } ;
13
+ use diesel:: { ExpressionMethods , QueryDsl } ;
14
+ use diesel_async:: { AsyncPgConnection as PgConnection , RunQueryDsl } ;
4
15
use editoast_derive:: ModelV2 ;
5
16
use serde_derive:: { Deserialize , Serialize } ;
6
17
use utoipa:: ToSchema ;
7
18
8
- #[ derive( Debug , Default , Clone , ModelV2 , Deserialize , Serialize ) ]
9
- #[ model( changeset( derive( Deserialize ) ) ) ]
19
+ #[ derive( Debug , Clone , ModelV2 , Deserialize , Serialize ) ]
10
20
#[ model( table = crate :: tables:: scenariov2) ]
21
+ #[ model( changeset( public) ) ]
11
22
pub struct ScenarioV2 {
12
23
pub id : i64 ,
13
24
pub infra_id : i64 ,
@@ -19,3 +30,119 @@ pub struct ScenarioV2 {
19
30
pub timetable_id : i64 ,
20
31
pub study_id : i64 ,
21
32
}
33
+
34
+ #[ derive( Debug , Clone , Deserialize , Serialize , QueryableByName , ToSchema ) ]
35
+ pub struct ScenarioV2WithDetails {
36
+ #[ serde( flatten) ]
37
+ #[ diesel( embed) ]
38
+ pub scenario : ScenarioV2 ,
39
+ #[ diesel( sql_type = Text ) ]
40
+ pub infra_name : String ,
41
+ // #[diesel(sql_type = Nullable<Text>)]
42
+ // pub electrical_profile_set_name: Option<String>,
43
+ #[ diesel( sql_type = Array <BigInt >) ]
44
+ pub train_schedule_ids : Vec < i64 > ,
45
+ #[ diesel( sql_type = BigInt ) ]
46
+ pub trains_count : i64 ,
47
+ }
48
+
49
+ impl ScenarioV2 {
50
+ pub async fn with_details_conn ( self , conn : & mut PgConnection ) -> Result < ScenarioV2WithDetails > {
51
+ use crate :: tables:: infra:: dsl as infra_dsl;
52
+ use crate :: tables:: trainschedulev2:: dsl:: * ;
53
+
54
+ let infra_name = infra_dsl:: infra
55
+ . filter ( infra_dsl:: id. eq ( self . infra_id ) )
56
+ . select ( infra_dsl:: name)
57
+ . first :: < String > ( conn)
58
+ . await ?;
59
+
60
+ // let electrical_profile_set_name = match self.electrical_profile_set_id.unwrap() {
61
+ // Some(electrical_profile_set) => Some(
62
+ // elec_dsl::electrical_profile_set
63
+ // .filter(elec_dsl::id.eq(electrical_profile_set))
64
+ // .select(elec_dsl::name)
65
+ // .first::<String>(conn)
66
+ // .await?,
67
+ // ),
68
+ // None => None,
69
+ // };
70
+
71
+ let train_schedule_ids = trainschedulev2
72
+ . filter ( timetable_id. eq ( self . timetable_id ) )
73
+ . select ( id)
74
+ . load :: < i64 > ( conn)
75
+ . await ?;
76
+
77
+ let trains_count = train_schedule_ids. len ( ) as i64 ;
78
+
79
+ Ok ( ScenarioV2WithDetails {
80
+ scenario : self ,
81
+ infra_name,
82
+ train_schedule_ids,
83
+ trains_count,
84
+ } )
85
+ }
86
+
87
+ pub async fn with_trains_count (
88
+ self ,
89
+ conn : & mut PgConnection ,
90
+ ) -> Result < ScenarioV2WithCountTrains > {
91
+ use crate :: tables:: infra:: dsl as infra_dsl;
92
+ use crate :: tables:: trainschedulev2:: dsl as schedule_dsl;
93
+ let trains_count = schedule_dsl:: trainschedulev2
94
+ . filter ( schedule_dsl:: timetable_id. eq ( self . timetable_id ) )
95
+ . count ( )
96
+ . get_result ( conn)
97
+ . await ?;
98
+ let infra_name = infra_dsl:: infra
99
+ . filter ( infra_dsl:: id. eq ( self . infra_id ) )
100
+ . select ( infra_dsl:: name)
101
+ . get_result ( conn)
102
+ . await ?;
103
+ Ok ( ScenarioV2WithCountTrains :: new_from_scenario (
104
+ self ,
105
+ trains_count,
106
+ infra_name,
107
+ ) )
108
+ }
109
+ }
110
+
111
+ #[ async_trait]
112
+ impl List < ( i64 , Ordering ) > for ScenarioV2 {
113
+ /// List all scenarios with the number of trains.
114
+ /// This functions takes a study_id to filter scenarios.
115
+ async fn list_conn (
116
+ conn : & mut PgConnection ,
117
+ page : i64 ,
118
+ page_size : i64 ,
119
+ params : ( i64 , Ordering ) ,
120
+ ) -> Result < PaginatedResponse < Self > > {
121
+ let study_id = params. 0 ;
122
+ let ordering = params. 1 . to_sql ( ) ;
123
+ let scenario_rows = sql_query ( format ! ( "WITH scenarios_with_train_counts AS (
124
+ SELECT t.*, COUNT(train_schedule.id) as trains_count
125
+ FROM scenariov2 as t
126
+ LEFT JOIN train_schedule ON t.timetable_id = train_schedule.timetable_id WHERE t.study_id = $1
127
+ GROUP BY t.id ORDER BY {ordering}
128
+ )
129
+ SELECT scenarios_with_train_counts.*, infra.name as infra_name
130
+ FROM scenarios_with_train_counts
131
+ JOIN infra ON infra.id = infra_id" ) )
132
+ . bind :: < BigInt , _ > ( study_id)
133
+ . paginate ( page, page_size)
134
+ . load_and_count :: < Row < ScenarioV2 > > ( conn) . await ?;
135
+
136
+ let results: Vec < ScenarioV2 > = scenario_rows
137
+ . results
138
+ . into_iter ( )
139
+ . map ( Self :: from_row)
140
+ . collect ( ) ;
141
+ Ok ( PaginatedResponse {
142
+ count : scenario_rows. count ,
143
+ previous : scenario_rows. previous ,
144
+ next : scenario_rows. next ,
145
+ results,
146
+ } )
147
+ }
148
+ }
0 commit comments