1#[cfg(feature = "mongo")]
6pub mod mongo;
7#[cfg(feature = "mongo")]
8pub use mongo::*;
9
10use chrono::{DateTime, Utc};
11use sea_orm::entity::prelude::*;
12use serde::{Deserialize, Serialize};
13
14pub trait BaseEntity: EntityTrait {
18 fn id_column() -> Self::Column;
20 fn create_time_column() -> Self::Column;
22 fn update_time_column() -> Self::Column;
24}
25
26pub trait SoftDeleteEntity: BaseEntity {
30 fn delete_time_column() -> Self::Column;
32}
33
34pub trait TenantEntity: BaseEntity {
38 fn tenant_id_column() -> Self::Column;
40}
41
42#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
46pub struct BaseFields {
47 #[serde(rename = "createTime")]
49 pub create_time: Option<DateTime<Utc>>,
50 #[serde(rename = "updateTime")]
52 pub update_time: Option<DateTime<Utc>>,
53}
54
55impl Default for BaseFields {
56 fn default() -> Self {
57 let now = Utc::now();
58 Self {
59 create_time: Some(now),
60 update_time: Some(now),
61 }
62 }
63}
64
65#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
67pub struct SoftDeleteFields {
68 #[serde(rename = "deleteTime", skip_serializing_if = "Option::is_none")]
70 pub delete_time: Option<DateTime<Utc>>,
71}
72
73#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize, Default)]
75pub struct TenantFields {
76 #[serde(rename = "tenantId", skip_serializing_if = "Option::is_none")]
78 pub tenant_id: Option<i64>,
79}
80
81pub type Id = i64;
83
84#[derive(Debug, Clone, Serialize, Deserialize, Default)]
86pub struct PageQuery {
87 #[serde(default = "default_page")]
89 pub page: u64,
90 #[serde(default = "default_size")]
92 pub size: u64,
93 pub order: Option<String>,
95 pub sort: Option<String>,
97 #[serde(rename = "keyWord")]
99 pub key_word: Option<String>,
100}
101
102fn default_page() -> u64 {
103 1
104}
105
106fn default_size() -> u64 {
107 20
108}
109
110impl PageQuery {
111 pub fn offset(&self) -> u64 {
113 (self.page.saturating_sub(1)) * self.size
114 }
115
116 pub fn is_asc(&self) -> bool {
118 self.sort
119 .as_ref()
120 .map(|s| s.to_lowercase() == "asc")
121 .unwrap_or(false)
122 }
123}
124
125#[derive(Debug, Clone, Serialize, Deserialize, Default)]
127pub struct ListQuery {
128 pub order: Option<String>,
130 pub sort: Option<String>,
132 #[serde(rename = "keyWord")]
134 pub key_word: Option<String>,
135}
136
137#[derive(Debug, Clone, Serialize, Deserialize)]
139pub struct DeleteParam {
140 pub ids: Vec<Id>,
142}
143
144#[derive(Debug, Clone, Serialize, Deserialize)]
146pub struct AddResult {
147 pub id: Id,
149}
150
151#[derive(Debug, Clone, Serialize, Deserialize)]
153pub struct BatchAddResult {
154 pub ids: Vec<Id>,
156}
157
158#[derive(Debug, Clone, Default)]
160pub struct QueryOption {
161 pub key_word_like_fields: Vec<String>,
163 pub select: Vec<String>,
165 pub field_like: Vec<FieldCondition>,
167 pub field_eq: Vec<FieldCondition>,
169 pub order_by: Vec<(String, bool)>, pub joins: Vec<JoinOption>,
173 pub where_and: Vec<String>,
175 pub left_join: Vec<JoinOption>,
177 pub extra_where: Vec<WhereFragment>,
179}
180
181impl QueryOption {
182 pub fn new() -> Self {
183 Self::default()
184 }
185
186 pub fn key_word_like_fields<I, S>(mut self, fields: I) -> Self
187 where
188 I: IntoIterator<Item = S>,
189 S: Into<String>,
190 {
191 self.key_word_like_fields = fields.into_iter().map(Into::into).collect();
192 self
193 }
194
195 pub fn select<I, S>(mut self, fields: I) -> Self
196 where
197 I: IntoIterator<Item = S>,
198 S: Into<String>,
199 {
200 self.select = fields.into_iter().map(Into::into).collect();
201 self
202 }
203
204 pub fn add_field_eq(
205 mut self,
206 column: impl Into<String>,
207 request_param: impl Into<String>,
208 ) -> Self {
209 self.field_eq
210 .push(FieldCondition::with_param(column, request_param));
211 self
212 }
213
214 pub fn add_field_like(
215 mut self,
216 column: impl Into<String>,
217 request_param: impl Into<String>,
218 ) -> Self {
219 self.field_like
220 .push(FieldCondition::with_param(column, request_param));
221 self
222 }
223
224 pub fn add_order_by(mut self, column: impl Into<String>, asc: bool) -> Self {
225 self.order_by.push((column.into(), asc));
226 self
227 }
228
229 pub fn add_left_join(
230 mut self,
231 entity: impl Into<String>,
232 alias: impl Into<String>,
233 condition: impl Into<String>,
234 join_type: JoinType,
235 ) -> Self {
236 self.left_join.push(JoinOption {
237 entity: entity.into(),
238 alias: alias.into(),
239 condition: condition.into(),
240 join_type,
241 });
242 self
243 }
244
245 pub fn add_where_and(mut self, cond: impl Into<String>) -> Self {
246 self.where_and.push(cond.into());
247 self
248 }
249
250 pub fn add_where_raw<I, V>(mut self, sql: impl Into<String>, params: I) -> Self
251 where
252 I: IntoIterator<Item = V>,
253 V: Into<serde_json::Value>,
254 {
255 self.extra_where.push(WhereFragment {
256 sql: sql.into(),
257 params: params.into_iter().map(Into::into).collect(),
258 });
259 self
260 }
261
262 pub fn add_where_with<F>(mut self, f: F) -> Self
264 where
265 F: FnOnce(WhereBuilder) -> WhereBuilder,
266 {
267 let builder = f(WhereBuilder::new());
268 self.extra_where.extend(builder.build());
269 self
270 }
271}
272
273#[derive(Debug, Clone)]
275pub struct FieldCondition {
276 pub column: String,
278 pub request_param: String,
280}
281
282impl FieldCondition {
283 pub fn new(column: impl Into<String>) -> Self {
284 let col = column.into();
285 Self {
286 request_param: col.clone(),
287 column: col,
288 }
289 }
290
291 pub fn with_param(column: impl Into<String>, request_param: impl Into<String>) -> Self {
292 Self {
293 column: column.into(),
294 request_param: request_param.into(),
295 }
296 }
297}
298
299#[derive(Debug, Clone)]
301pub struct JoinOption {
302 pub entity: String,
304 pub alias: String,
306 pub condition: String,
308 pub join_type: JoinType,
310}
311
312#[derive(Debug, Clone, Copy, PartialEq, Eq, Default)]
314pub enum JoinType {
315 Inner,
317 #[default]
319 Left,
320}
321
322#[derive(Debug, Clone)]
324pub struct WhereFragment {
325 pub sql: String,
327 pub params: Vec<serde_json::Value>,
329}
330
331#[derive(Default)]
333pub struct WhereBuilder {
334 frags: Vec<WhereFragment>,
335}
336
337impl WhereBuilder {
338 pub fn new() -> Self {
339 Self { frags: Vec::new() }
340 }
341
342 pub fn eq(mut self, column: impl Into<String>, value: impl Into<serde_json::Value>) -> Self {
344 self.frags.push(WhereFragment {
345 sql: format!("{} = ?", column.into()),
346 params: vec![value.into()],
347 });
348 self
349 }
350
351 pub fn like(mut self, column: impl Into<String>, value: impl Into<String>) -> Self {
353 self.frags.push(WhereFragment {
354 sql: format!("{} LIKE ?", column.into()),
355 params: vec![serde_json::Value::String(format!("%{}%", value.into()))],
356 });
357 self
358 }
359
360 pub fn raw<I, V>(mut self, sql: impl Into<String>, params: I) -> Self
362 where
363 I: IntoIterator<Item = V>,
364 V: Into<serde_json::Value>,
365 {
366 self.frags.push(WhereFragment {
367 sql: sql.into(),
368 params: params.into_iter().map(Into::into).collect(),
369 });
370 self
371 }
372
373 pub fn build(self) -> Vec<WhereFragment> {
374 self.frags
375 }
376}