airlab_lib/model/
view_panel_element.rs1use 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}