docbox_database/models/
document_box.rs1use crate::{DbExecutor, DbResult};
2use chrono::{DateTime, Utc};
3use serde::{Deserialize, Serialize};
4use sqlx::{postgres::PgQueryResult, prelude::FromRow};
5use utoipa::ToSchema;
6
7pub type DocumentBoxScopeRaw = String;
8pub type DocumentBoxScopeRawRef<'a> = &'a str;
9
10#[derive(Debug, Clone, FromRow, Serialize, ToSchema)]
11pub struct DocumentBox {
12 pub scope: DocumentBoxScopeRaw,
14 pub created_at: DateTime<Utc>,
16}
17
18#[derive(Debug, Clone, Serialize, Deserialize, ToSchema)]
19pub struct WithScope<T> {
20 #[serde(flatten)]
21 pub data: T,
22 pub scope: DocumentBoxScopeRaw,
23}
24
25impl<T> WithScope<T> {
26 pub fn new(data: T, scope: DocumentBoxScopeRaw) -> WithScope<T> {
27 WithScope { data, scope }
28 }
29}
30
31#[derive(FromRow)]
32struct CountResult {
33 count: i64,
34}
35
36impl DocumentBox {
37 pub async fn query(
39 db: impl DbExecutor<'_>,
40 offset: u64,
41 limit: u64,
42 ) -> DbResult<Vec<DocumentBox>> {
43 sqlx::query_as(
44 r#"
45 SELECT * FROM "docbox_boxes"
46 ORDER BY "created_at" DESC
47 OFFSET $1 LIMIT $2"#,
48 )
49 .bind(offset as i64)
50 .bind(limit as i64)
51 .fetch_all(db)
52 .await
53 }
54
55 pub async fn total(db: impl DbExecutor<'_>) -> DbResult<i64> {
57 let result: CountResult =
58 sqlx::query_as(r#"SELECT COUNT(*) as "count" FROM "docbox_boxes""#)
59 .fetch_one(db)
60 .await?;
61
62 Ok(result.count)
63 }
64
65 pub async fn search_query(
67 db: impl DbExecutor<'_>,
68 query: &str,
69 offset: u64,
70 limit: u64,
71 ) -> DbResult<Vec<DocumentBox>> {
72 sqlx::query_as(
73 r#"
74 SELECT * FROM "docbox_boxes"
75 WHERE ($3 IS NULL OR "scope" ILIKE $3)
76 ORDER BY "created_at" DESC
77 OFFSET $1 LIMIT $2"#,
78 )
79 .bind(offset as i64)
80 .bind(limit as i64)
81 .bind(query)
82 .fetch_all(db)
83 .await
84 }
85
86 pub async fn search_total(db: impl DbExecutor<'_>, query: &str) -> DbResult<i64> {
88 let result: CountResult = sqlx::query_as(
89 r#"
90 SELECT COUNT(*) as "count" FROM "docbox_boxes"
91 WHERE ($1 IS NULL OR "scope" ILIKE $1)
92 "#,
93 )
94 .bind(query)
95 .fetch_one(db)
96 .await?;
97
98 Ok(result.count)
99 }
100
101 pub async fn find_by_scope(
103 db: impl DbExecutor<'_>,
104 scope: &DocumentBoxScopeRaw,
105 ) -> DbResult<Option<DocumentBox>> {
106 sqlx::query_as(r#"SELECT * FROM "docbox_boxes" WHERE "scope" = $1"#)
107 .bind(scope)
108 .fetch_optional(db)
109 .await
110 }
111
112 pub async fn create(db: impl DbExecutor<'_>, scope: String) -> DbResult<DocumentBox> {
113 let document_box = DocumentBox {
114 scope,
115 created_at: Utc::now(),
116 };
117
118 sqlx::query(r#"INSERT INTO "docbox_boxes" ("scope", "created_at") VALUES ($1, $2)"#)
119 .bind(document_box.scope.as_str())
120 .bind(document_box.created_at)
121 .execute(db)
122 .await?;
123
124 Ok(document_box)
125 }
126
127 pub async fn delete(&self, db: impl DbExecutor<'_>) -> DbResult<PgQueryResult> {
129 sqlx::query(r#"DELETE FROM "docbox_boxes" WHERE "scope" = $1"#)
130 .bind(&self.scope)
131 .execute(db)
132 .await
133 }
134}