rust_cutil/cutil/
pos.rs

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}