1use std::collections::HashMap;
2use std::str::FromStr;
3
4use crate::cutil::extract::Extract;
5use crate::cutil::meta::R;
6use crate::cutil::paged::Paged;
7use sea_orm::{DatabaseConnection, EntityTrait, FromQueryResult, PaginatorTrait, QueryOrder, Select};
8use serde::{Deserialize, Serialize};
9use utoipa::ToSchema;
10
11#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
12pub struct Pos {
13 pub page_index: u64,
14 pub page_size: u64,
15 pub order_by: Vec<String>,
16}
17
18impl Pos {
19 pub fn default() -> Self {
20 Pos {
21 page_index: 0,
22 page_size: 10,
23 order_by: vec![],
24 }
25 }
26 pub fn first() -> Self {
27 Pos {
28 page_index: 0,
29 page_size: 1,
30 order_by: vec![],
31 }
32 }
33
34 pub fn new(page_index: u64, page_size: u64, order_by: Vec<String>) -> Self {
35 Pos {
36 page_index,
37 page_size,
38 order_by,
39 }
40 }
41 pub fn from(params: HashMap<String, String>) -> Self {
42 let page_index = params.extract_u64_default("page_index", 0);
43 let page_size = params.extract_u64_default("page_size", 10);
44 let order_by: Vec<String> = params.extract_vec("order_by");
45
46 Pos {
47 page_index,
48 page_size,
49 order_by,
50 }
51 }
52
53 pub async fn paged<M, E, D>(&self, conn: &DatabaseConnection, mut query: Select<E>) -> R<Paged<D>>
54 where
55 M: FromQueryResult + Send + Sync,
56 E: EntityTrait,
57 D: FromQueryResult + Send + Sync,
58 {
59 for item in &self.order_by {
60 let list = item.split('.').collect::<Vec<_>>();
61 if list.len() != 2 {
62 continue;
63 }
64
65 let (column_name, sort_direction) = (list[0], list[1]);
66
67 if let Ok(column) = E::Column::from_str(column_name) {
68 query = match sort_direction.to_lowercase().as_str() {
69 "asc" => query.order_by_asc(column),
70 _ => query.order_by_desc(column),
71 };
72 }
73 }
74 let page_size = if self.page_size == 0 { 1 } else { self.page_size };
75 let query = query.into_model::<D>();
76 let paginator = query.paginate(conn, page_size);
77
78 let items: Vec<D> = paginator.fetch_page(self.page_index).await?;
79
80 let num = paginator.num_items_and_pages().await?;
81
82 let paged = Paged {
83 page_index: self.page_index,
84 page_size,
85 page_count: num.number_of_pages,
86 items,
87 item_count: num.number_of_items,
88 };
89 Ok(paged)
90 }
91}