airlab_lib/model/
validation_file.rs

1use crate::ctx::Ctx;
2use crate::model::ModelManager;
3use crate::model::Result;
4use crate::model::base::{self, DbBmc};
5//use chrono::prelude::*;
6use modql::field::Fields;
7use modql::filter::{FilterNodes, ListOptions, OpValsInt64, OpValsString};
8use serde::{Deserialize, Serialize};
9use sqlx::FromRow;
10
11impl ValidationFileBmc {
12    #[must_use]
13    pub fn get_create_sql(drop_table: bool) -> String {
14        let table = Self::TABLE;
15        format!(
16            r##"{}
17create table if not exists "{table}" (
18  id serial primary key,
19  validation_id integer NOT NULL,
20  created_by integer NOT NULL,
21  hash character varying NOT NULL,
22  size integer,
23  name character varying,
24  extension character varying NOT NULL,
25  description character varying,
26  meta jsonb,
27  created_at timestamp with time zone DEFAULT now() NOT NULL
28);
29CREATE INDEX "IDX_validation_file_created_by" ON validation_file USING btree (created_by);
30CREATE INDEX "IDX_validation_file_hash" ON validation_file USING btree (hash);
31CREATE INDEX "IDX_validation_file_validation_id" ON validation_file USING btree (validation_id);
32        "##,
33            if drop_table {
34                format!("drop table if exists {table};")
35            } else {
36                String::new()
37            }
38        )
39    }
40}
41
42#[derive(Debug, Clone, Fields, FromRow, Serialize, Deserialize)]
43pub struct ValidationFile {
44    pub id: i32,
45
46    #[serde(rename = "validationId")]
47    pub validation_id: i32,
48    #[serde(rename = "createdBy")]
49    pub created_by: i32,
50    pub hash: String,
51    pub size: i32,
52    pub name: Option<String>,
53    pub extension: String,
54    pub description: Option<String>,
55    pub meta: Option<serde_json::Value>,
56    #[serde(rename = "createdAt")]
57    pub created_at: chrono::DateTime<chrono::Utc>,
58}
59
60#[derive(Fields, Deserialize, Clone, Debug)]
61pub struct ValidationFileForCreate {
62    #[serde(rename = "validationId")]
63    pub validation_id: i32,
64    #[serde(rename = "createdBy")]
65    pub created_by: i32,
66    pub hash: String,
67    pub size: i32,
68    pub name: Option<String>,
69    pub extension: String,
70    pub description: Option<String>,
71    //pub meta: Option<String>,
72    #[serde(rename = "createdAt")]
73    pub created_at: chrono::DateTime<chrono::Utc>,
74}
75
76#[derive(Fields, Default, Deserialize, Debug)]
77pub struct ValidationFileForUpdate {
78    pub hash: String,
79    pub size: i32,
80    pub name: Option<String>,
81    pub extension: Option<String>,
82    pub description: Option<String>,
83}
84
85#[derive(FilterNodes, Deserialize, Default, Debug)]
86pub struct ValidationFileFilter {
87    id: Option<OpValsInt64>,
88    validation_id: Option<OpValsInt64>,
89
90    name: Option<OpValsString>,
91}
92
93pub struct ValidationFileBmc;
94
95impl DbBmc for ValidationFileBmc {
96    const TABLE: &'static str = "validation_file";
97}
98
99impl ValidationFileBmc {
100    pub async fn create(
101        ctx: &Ctx,
102        mm: &ModelManager,
103        validation_file_c: ValidationFileForCreate,
104    ) -> Result<i32> {
105        base::create::<Self, _>(ctx, mm, validation_file_c).await
106    }
107    pub async fn create_full(
108        ctx: &Ctx,
109        mm: &ModelManager,
110        validation_file_c: ValidationFile,
111    ) -> Result<i32> {
112        base::create::<Self, _>(ctx, mm, validation_file_c).await
113    }
114
115    pub async fn get(ctx: &Ctx, mm: &ModelManager, id: i32) -> Result<ValidationFile> {
116        base::get::<Self, _>(ctx, mm, id).await
117    }
118
119    pub async fn list(
120        ctx: &Ctx,
121        mm: &ModelManager,
122        filters: Option<Vec<ValidationFileFilter>>,
123        list_options: Option<ListOptions>,
124    ) -> Result<Vec<ValidationFile>> {
125        base::list::<Self, _, _>(ctx, mm, filters, list_options).await
126    }
127
128    pub async fn update(
129        ctx: &Ctx,
130        mm: &ModelManager,
131        id: i32,
132        validation_file_u: ValidationFileForUpdate,
133    ) -> Result<()> {
134        base::update::<Self, _>(ctx, mm, id, validation_file_u).await
135    }
136
137    pub async fn delete(ctx: &Ctx, mm: &ModelManager, id: i32) -> Result<()> {
138        base::delete::<Self>(ctx, mm, id).await
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145    use crate::_dev_utils;
146    use crate::model::Error;
147    use anyhow::Result;
148    use serde_json::json;
149
150    #[ignore]
151    #[tokio::test]
152    async fn test_validation_file_create_ok() -> Result<()> {
153        let mm = ModelManager::new().await?;
154        let ctx = Ctx::root_ctx();
155        let fx_name = "test_create_ok name";
156
157        let validation_file_c = ValidationFileForCreate {
158            name: None,
159            created_by: 261,
160            validation_id: 2221,
161            hash: String::new(),
162            size: 0,
163            extension: "pdf".into(),
164            description: None,
165            created_at: chrono::offset::Utc::now(),
166        };
167        let id = ValidationFileBmc::create(&ctx, &mm, validation_file_c).await?;
168
169        let validation_file = ValidationFileBmc::get(&ctx, &mm, id).await?;
170        assert_eq!(validation_file.name, Some(fx_name.into()));
171
172        ValidationFileBmc::delete(&ctx, &mm, id).await?;
173
174        Ok(())
175    }
176
177    #[ignore]
178    #[tokio::test]
179    async fn test_validation_file_get_err_not_found() -> Result<()> {
180        let mm = ModelManager::new().await?;
181        let ctx = Ctx::root_ctx();
182        let fx_id = 100;
183
184        let res = ValidationFileBmc::get(&ctx, &mm, fx_id).await;
185
186        assert!(
187            matches!(
188                res,
189                Err(Error::EntityNotFound {
190                    entity: "validation_file",
191                    id: 100
192                })
193            ),
194            "EntityNotFound not matching"
195        );
196
197        Ok(())
198    }
199
200    #[ignore]
201    #[tokio::test]
202    async fn test_validation_file_list_all_ok() -> Result<()> {
203        let mm = ModelManager::new().await?;
204        let ctx = Ctx::root_ctx();
205        let tname = "test_validation_file_list_all_ok";
206        let seeds = _dev_utils::get_validation_file_seed(tname);
207        _dev_utils::seed_validation_files(&ctx, &mm, &seeds).await?;
208
209        let validation_files = ValidationFileBmc::list(&ctx, &mm, None, None).await?;
210
211        let validation_files: Vec<ValidationFile> = validation_files.into_iter().collect();
212        assert_eq!(
213            validation_files.len(),
214            4,
215            "number of seeded validation_files."
216        );
217
218        if false {
219            for validation_file in validation_files.iter() {
220                ValidationFileBmc::delete(&ctx, &mm, validation_file.id).await?;
221            }
222        }
223
224        Ok(())
225    }
226
227    #[ignore]
228    #[tokio::test]
229    async fn test_validation_file_list_by_filter_ok() -> Result<()> {
230        let mm = ModelManager::new().await?;
231        let ctx = Ctx::root_ctx();
232        let tname = "test_validation_file_list_by_filter_ok";
233        let seeds = _dev_utils::get_validation_file_seed(tname);
234        _dev_utils::seed_validation_files(&ctx, &mm, &seeds).await?;
235
236        let filters: Vec<ValidationFileFilter> = serde_json::from_value(json!([
237            {
238                "name": {
239                    "$endsWith": ".a",
240                    "$containsAny": ["01", "02"]
241                }
242            },
243            {
244                "name": {"$contains": "03"}
245            }
246        ]))?;
247        let list_options = serde_json::from_value(json!({
248            "order_bys": "!id"
249        }))?;
250        let validation_files =
251            ValidationFileBmc::list(&ctx, &mm, Some(filters), Some(list_options)).await?;
252
253        assert_eq!(validation_files.len(), 3);
254        assert_eq!(validation_files[0].name, Some("wrong".into()));
255
256        if false {
257            let validation_files = ValidationFileBmc::list(
258                &ctx,
259                &mm,
260                Some(serde_json::from_value(json!([{
261                    "name": {"$startsWith": "test_list_by_filter_ok"}
262                }]))?),
263                None,
264            )
265            .await?;
266            assert_eq!(validation_files.len(), 5);
267            for validation_file in validation_files.iter() {
268                ValidationFileBmc::delete(&ctx, &mm, validation_file.id).await?;
269            }
270        }
271
272        Ok(())
273    }
274
275    #[ignore]
276    #[tokio::test]
277    async fn test_validation_file_update_ok() -> Result<()> {
278        let mm = ModelManager::new().await?;
279        let ctx = Ctx::root_ctx();
280        let tname = "test_validation_file_update_ok";
281        let seeds = _dev_utils::get_validation_file_seed(tname);
282        let fx_name_new = "test_update_ok - validation_file 01 - new";
283        let fx_validation_file = _dev_utils::seed_validation_files(&ctx, &mm, &seeds)
284            .await?
285            .remove(0);
286
287        ValidationFileBmc::update(
288            &ctx,
289            &mm,
290            fx_validation_file.id,
291            ValidationFileForUpdate {
292                name: Some(fx_name_new.to_string()),
293                ..Default::default()
294            },
295        )
296        .await?;
297
298        let validation_file = ValidationFileBmc::get(&ctx, &mm, fx_validation_file.id).await?;
299        assert_eq!(validation_file.name, Some(fx_name_new.into()));
300
301        Ok(())
302    }
303
304    #[ignore]
305    #[tokio::test]
306    async fn test_validation_file_delete_err_not_found() -> Result<()> {
307        let mm = ModelManager::new().await?;
308        let ctx = Ctx::root_ctx();
309        let fx_id = 100;
310
311        let res = ValidationFileBmc::delete(&ctx, &mm, fx_id).await;
312
313        assert!(
314            matches!(
315                res,
316                Err(Error::EntityNotFound {
317                    entity: "validation_file",
318                    id: 100
319                })
320            ),
321            "EntityNotFound not matching"
322        );
323
324        Ok(())
325    }
326}