airlab_lib/model/
view_panel_element.rs

1use crate::ctx::Ctx;
2use crate::model::conjugate::{Conjugate, ConjugateBmc, ConjugateFilter};
3use crate::model::lot::{Lot, LotBmc, LotFilter};
4use crate::model::panel_element::{PanelElement, PanelElementBmc, PanelElementFilter};
5use serde_json::json;
6
7use crate::model::ModelManager;
8use crate::model::Result;
9use modql::filter::ListOptions;
10use serde::{Deserialize, Serialize};
11use std::collections::HashMap;
12
13#[derive(Serialize, Deserialize, Debug, Clone, Default)]
14pub struct MinLot {
15    id: i32,
16    name: String,
17}
18
19#[derive(Serialize, Deserialize, Debug, Clone, Default)]
20pub struct MinConjugate {
21    id: i32,
22    #[serde(rename = "tubeNumber")]
23    tube_number: i32,
24    lot: MinLot,
25}
26
27#[derive(Serialize, Deserialize, Debug, Clone, Default)]
28pub struct ViewPanelElement {
29    pub id: i32,
30    #[serde(rename = "panelId")]
31    pub panel_id: i32,
32    #[serde(rename = "conjugateId")]
33    pub conjugate_id: i32,
34    #[serde(rename = "dilutionType")]
35    pub dilution_type: i32,
36    pub concentration: Option<f32>,
37    pub conjugate: MinConjugate,
38}
39
40pub struct ViewPanelElementBmc;
41
42impl ViewPanelElementBmc {
43    pub async fn get(ctx: &Ctx, mm: &ModelManager, id: i32) -> Result<ViewPanelElement> {
44        let element = PanelElementBmc::get(ctx, mm, id).await?;
45        let conjugate = ConjugateBmc::get(ctx, mm, element.conjugate_id).await?;
46        let lot = LotBmc::get(ctx, mm, conjugate.lot_id).await?;
47        let ret = ViewPanelElement {
48            id: element.id,
49            panel_id: element.panel_id,
50            conjugate_id: element.conjugate_id,
51            concentration: element.concentration,
52            dilution_type: i32::from(element.dilution_type),
53            conjugate: MinConjugate {
54                id: conjugate.id,
55                tube_number: conjugate.tube_number,
56                lot: MinLot {
57                    id: lot.id,
58                    name: lot.name,
59                },
60            },
61        };
62
63        Ok(ret)
64    }
65    pub async fn list(
66        ctx: &Ctx,
67        mm: &ModelManager,
68        filters: Option<Vec<PanelElementFilter>>,
69        list_options: Option<ListOptions>,
70    ) -> Result<Vec<ViewPanelElement>> {
71        let elements: Vec<PanelElement> =
72            PanelElementBmc::list(ctx, mm, filters, list_options).await?;
73        let conj_ids: Vec<i32> = elements.iter().map(|e| e.conjugate_id).collect();
74        let mut conj_map = HashMap::new();
75        let filters: Vec<ConjugateFilter> =
76            serde_json::from_value(json!([{"id": {"$in": conj_ids}}])).unwrap_or(vec![]);
77        let op = ListOptions {
78            limit: Some(10_000),
79            ..Default::default()
80        };
81        let conjugates: Vec<Conjugate> =
82            ConjugateBmc::list(ctx, mm, Some(filters), Some(op)).await?;
83        let lot_ids: Vec<i32> = conjugates.iter().map(|e| e.lot_id).collect();
84        for conjugate in conjugates {
85            conj_map.insert(conjugate.id, conjugate);
86        }
87        let mut lot_map = HashMap::new();
88        let filters: Vec<LotFilter> =
89            serde_json::from_value(json!([{"id": {"$in": lot_ids}}])).unwrap_or(vec![]);
90        let op = ListOptions {
91            limit: Some(10_000),
92            ..Default::default()
93        };
94        let lots: Vec<Lot> = LotBmc::list(ctx, mm, Some(filters), Some(op)).await?;
95        for lot in lots {
96            lot_map.insert(lot.id, lot);
97        }
98        let mut returns = vec![];
99        for element in elements {
100            if let Some(conj) = conj_map.get(&element.conjugate_id) {
101                if let Some(lot) = lot_map.get(&conj.lot_id) {
102                    returns.push(ViewPanelElement {
103                        id: element.id,
104                        panel_id: element.panel_id,
105                        conjugate_id: element.conjugate_id,
106                        concentration: element.concentration,
107                        dilution_type: i32::from(element.dilution_type),
108                        conjugate: MinConjugate {
109                            id: conj.id,
110                            tube_number: conj.tube_number,
111                            lot: MinLot {
112                                id: lot.id,
113                                name: lot.name.clone(),
114                            },
115                        },
116                    });
117                }
118            }
119        }
120
121        Ok(returns)
122    }
123}
124
125#[cfg(test)]
126mod tests {
127    use super::*;
128    use anyhow::Result;
129
130    #[ignore]
131    #[tokio::test]
132    async fn test_view_panel_list_all_ok() -> Result<()> {
133        let mm = ModelManager::new().await?;
134        let ctx = Ctx::root_ctx();
135
136        let _panels = ViewPanelElementBmc::list(&ctx, &mm, None, None).await?;
137
138        Ok(())
139    }
140}