docbox_database/models/
document_box.rs

1use 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    /// Scope for the document box
13    pub scope: DocumentBoxScopeRaw,
14    /// Date of creation for the document box
15    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    /// Get a page from the document boxes list
38    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    /// Get the total number of document boxes in the tenant
56    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    /// Get a page from the document boxes list based on a search query
66    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    /// Get the total number of document boxes in the tenant for the specific search query
87    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    /// Find a specific document box by scope within a tenant
102    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    /// Deletes the document box
128    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}