From a32ca5479cf7801511f059a8254beeb9dccc5926 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Tue, 22 Aug 2023 17:22:25 +0100 Subject: [PATCH 01/10] Add temperature_log schema to diesel --- .../repository/src/db_diesel/diesel_schema.rs | 3 +- server/repository/src/db_diesel/mod.rs | 4 + .../src/db_diesel/temperature_log.rs | 121 ++++++++++++++++++ .../src/db_diesel/temperature_log_row.rs | 104 +++++++++++++++ 4 files changed, 231 insertions(+), 1 deletion(-) create mode 100644 server/repository/src/db_diesel/temperature_log.rs create mode 100644 server/repository/src/db_diesel/temperature_log_row.rs diff --git a/server/repository/src/db_diesel/diesel_schema.rs b/server/repository/src/db_diesel/diesel_schema.rs index 13c00c2af5..2755c9dbe9 100644 --- a/server/repository/src/db_diesel/diesel_schema.rs +++ b/server/repository/src/db_diesel/diesel_schema.rs @@ -10,13 +10,14 @@ use super::{ program_requisition::program_requisition_settings_row::program_requisition_settings, requisition_line_row::requisition_line, requisition_row::requisition, sensor_row::sensor, stock_line_row::stock_line, stocktake_line_row::stocktake_line, stocktake_row::stocktake, - store_row::store, unit_row::unit, user_row::user_account, + store_row::store, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, }; allow_tables_to_appear_in_same_query!( unit, location, sensor, + temperature_log, item, stock_line, name, diff --git a/server/repository/src/db_diesel/mod.rs b/server/repository/src/db_diesel/mod.rs index 1a289e6cd2..8ab5c563c5 100644 --- a/server/repository/src/db_diesel/mod.rs +++ b/server/repository/src/db_diesel/mod.rs @@ -73,6 +73,8 @@ mod store_row; mod sync_buffer; mod sync_log; mod sync_log_row; +mod temperature_log; +mod temperature_log_row; mod unit_row; mod user; mod user_permission; @@ -146,6 +148,8 @@ pub use store_row::*; pub use sync_buffer::*; pub use sync_log::*; pub use sync_log_row::*; +pub use temperature_log::*; +pub use temperature_log_row::*; pub use unit_row::*; pub use user::*; pub use user_permission::*; diff --git a/server/repository/src/db_diesel/temperature_log.rs b/server/repository/src/db_diesel/temperature_log.rs new file mode 100644 index 0000000000..064b8f091a --- /dev/null +++ b/server/repository/src/db_diesel/temperature_log.rs @@ -0,0 +1,121 @@ +use super::{ + temperature_log_row::{temperature_log, temperature_log::dsl as temperature_log_dsl}, + DBType, TemperatureLogRow, StorageConnection, +}; +use diesel::prelude::*; + +use crate::{ + diesel_macros::{apply_equal_filter, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureLog { + pub temperature_log_row: TemperatureLogRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureLogFilter { + pub id: Option>, + pub sensor_id: Option>, + pub store_id: Option>, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureLogSortField { + Id, + Timestamp, + Temperature, +} + +pub type TemperatureLogSort = Sort; + +pub struct TemperatureLogRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureLogRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureLogRepository { connection } + } + + pub fn count(&self, filter: Option) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter(&self, filter: TemperatureLogFilter) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureLogSortField::Id => { + apply_sort_no_case!(query, sort, temperature_log_dsl::id) + } + TemperatureLogSortField::Timestamp => { + apply_sort_no_case!(query, sort, temperature_log_dsl::timestamp) + } + TemperatureLogSortField::Temperature => { + apply_sort_no_case!(query, sort, temperature_log_dsl::temperature) + } + } + } else { + query = query.order(temperature_log_dsl::timestamp.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_log::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_log::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_log_dsl::id); + apply_equal_filter!(query, filter.sensor_id, temperature_log_dsl::sensor_id); + apply_equal_filter!(query, filter.store_id, temperature_log_dsl::store_id); + } + + query +} + +pub fn to_domain(temperature_log_row: TemperatureLogRow) -> TemperatureLog { + TemperatureLog { temperature_log_row } +} + +impl TemperatureLogFilter { + pub fn new() -> TemperatureLogFilter { + TemperatureLogFilter { + id: None, + sensor_id: None, + store_id: None, + } + } + + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { + self.sensor_id = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_log_row.rs b/server/repository/src/db_diesel/temperature_log_row.rs new file mode 100644 index 0000000000..6580c8aca4 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_log_row.rs @@ -0,0 +1,104 @@ +use super::{ + location_row::location, sensor_row::sensor, temperature_log_row::temperature_log::dsl as temperature_log_dsl, store_row::store, + StorageConnection, +}; + +use crate::repository_error::RepositoryError; + +use chrono::NaiveDateTime; +use diesel::prelude::*; + +table! { + temperature_log (id) { + id -> Text, + temperature -> Float, + sensor_id -> Text, + location_id -> Nullable, + store_id -> Nullable, + timestamp -> Timestamp, + } +} + +table! { + #[sql_name = "temperature_log"] + temperature_log_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_log -> sensor (sensor_id)); +joinable!(temperature_log -> store (store_id)); +joinable!(temperature_log -> location (location_id)); + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_log"] +pub struct TemperatureLogRow { + pub id: String, + pub temperature: f32, + pub sensor_id: String, + pub location_id: Option, + pub store_id: Option, + pub timestamp: NaiveDateTime, +} + +impl Default for TemperatureLogRow { + fn default() -> Self { + TemperatureLogRow { + id: Default::default(), + temperature: Default::default(), + sensor_id: Default::default(), + location_id: None, + store_id: None, + timestamp: Default::default(), + } + } +} +pub struct TemperatureLogRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureLogRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureLogRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_log_dsl::temperature_log) + .values(row) + .on_conflict(temperature_log_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_log_dsl::temperature_log) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { + let result = temperature_log_dsl::temperature_log + .filter(temperature_log_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { + Ok(temperature_log_dsl::temperature_log + .filter(temperature_log_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} From 4c9f823426397c234c2f2c8b3207f0b7d636f446 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Wed, 23 Aug 2023 17:49:45 +0100 Subject: [PATCH 02/10] Added schema for temperature_breach --- .../repository/src/db_diesel/diesel_schema.rs | 3 +- server/repository/src/db_diesel/mod.rs | 4 + .../src/db_diesel/temperature_breach.rs | 160 ++++++++++++++++++ .../src/db_diesel/temperature_breach_row.rs | 135 +++++++++++++++ 4 files changed, 301 insertions(+), 1 deletion(-) create mode 100644 server/repository/src/db_diesel/temperature_breach.rs create mode 100644 server/repository/src/db_diesel/temperature_breach_row.rs diff --git a/server/repository/src/db_diesel/diesel_schema.rs b/server/repository/src/db_diesel/diesel_schema.rs index 2755c9dbe9..8bf050898c 100644 --- a/server/repository/src/db_diesel/diesel_schema.rs +++ b/server/repository/src/db_diesel/diesel_schema.rs @@ -10,7 +10,7 @@ use super::{ program_requisition::program_requisition_settings_row::program_requisition_settings, requisition_line_row::requisition_line, requisition_row::requisition, sensor_row::sensor, stock_line_row::stock_line, stocktake_line_row::stocktake_line, stocktake_row::stocktake, - store_row::store, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, + store_row::store, temperature_breach_row::temperature_breach, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, }; allow_tables_to_appear_in_same_query!( @@ -18,6 +18,7 @@ allow_tables_to_appear_in_same_query!( location, sensor, temperature_log, + temperature_breach, item, stock_line, name, diff --git a/server/repository/src/db_diesel/mod.rs b/server/repository/src/db_diesel/mod.rs index 8ab5c563c5..493e00267b 100644 --- a/server/repository/src/db_diesel/mod.rs +++ b/server/repository/src/db_diesel/mod.rs @@ -73,6 +73,8 @@ mod store_row; mod sync_buffer; mod sync_log; mod sync_log_row; +mod temperature_breach; +mod temperature_breach_row; mod temperature_log; mod temperature_log_row; mod unit_row; @@ -148,6 +150,8 @@ pub use store_row::*; pub use sync_buffer::*; pub use sync_log::*; pub use sync_log_row::*; +pub use temperature_breach::*; +pub use temperature_breach_row::*; pub use temperature_log::*; pub use temperature_log_row::*; pub use unit_row::*; diff --git a/server/repository/src/db_diesel/temperature_breach.rs b/server/repository/src/db_diesel/temperature_breach.rs new file mode 100644 index 0000000000..f62778deb0 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach.rs @@ -0,0 +1,160 @@ +use super::{ + temperature_breach_row::{temperature_breach, temperature_breach::dsl as temperature_breach_dsl}, + DBType, TemperatureBreachRow, TemperatureBreachRowType, StorageConnection, +}; +use diesel::prelude::*; +use util::inline_init; + +use crate::{ + diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureBreach { + pub temperature_breach_row: TemperatureBreachRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureBreachFilter { + pub id: Option>, + pub r#type: Option>, + pub sensor_id: Option>, + pub store_id: Option>, + pub start_timestamp: Option, + pub end_timestamp: Option, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureBreachSortField { + Id, + StartTimestamp, + EndTimestamp, +} + +pub type TemperatureBreachSort = Sort; + +pub struct TemperatureBreachRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachRepository { connection } + } + + pub fn count(&self, filter: Option) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter(&self, filter: TemperatureBreachFilter) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureBreachSortField::Id => { + apply_sort_no_case!(query, sort, temperature_breach_dsl::id) + } + TemperatureBreachSortField::StartTimestamp => { + apply_sort!(query, sort, temperature_breach_dsl::start_timestamp) + } + TemperatureBreachSortField::EndTimestamp => { + apply_sort!(query, sort, temperature_breach_dsl::end_timestamp) + } + } + } else { + query = query.order(temperature_breach_dsl::start_timestamp.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_breach::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_breach::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_breach_dsl::id); + apply_equal_filter!(query, filter.sensor_id, temperature_breach_dsl::sensor_id); + apply_equal_filter!(query, filter.store_id, temperature_breach_dsl::store_id); + apply_equal_filter!(query, filter.r#type, temperature_breach_dsl::type_); + apply_date_time_filter!(query, filter.start_timestamp, temperature_breach_dsl::start_timestamp); + apply_date_time_filter!(query, filter.end_timestamp, temperature_breach_dsl::end_timestamp); + } + + query +} + +impl TemperatureBreachRowType { + pub fn equal_to(&self) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.equal_to = Some(self.clone())) + } + + pub fn not_equal_to(&self) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.not_equal_to = Some(self.clone())) + } + + pub fn equal_any(value: Vec) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.equal_any = Some(value)) + } +} + +pub fn to_domain(temperature_breach_row: TemperatureBreachRow) -> TemperatureBreach { + TemperatureBreach { temperature_breach_row } +} + +impl TemperatureBreachFilter { + pub fn new() -> TemperatureBreachFilter { + TemperatureBreachFilter { + id: None, + sensor_id: None, + store_id: None, + start_timestamp: None, + end_timestamp: None, + r#type: None, + } + } + + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { + self.sensor_id = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } + + pub fn start_timestamp(mut self, filter: DatetimeFilter) -> Self { + self.start_timestamp = Some(filter); + self + } + + pub fn end_timestamp(mut self, filter: DatetimeFilter) -> Self { + self.end_timestamp = Some(filter); + self + } + + pub fn r#type(mut self, filter: EqualFilter) -> Self { + self.r#type = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_breach_row.rs b/server/repository/src/db_diesel/temperature_breach_row.rs new file mode 100644 index 0000000000..76d195c2df --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_row.rs @@ -0,0 +1,135 @@ +use super::{ + location_row::location, sensor_row::sensor, temperature_breach_row::temperature_breach::dsl as temperature_breach_dsl, store_row::store, + StorageConnection, +}; + +use crate::repository_error::RepositoryError; + +use chrono::NaiveDateTime; +use diesel::prelude::*; +use diesel_derive_enum::DbEnum; +use serde::{Deserialize, Serialize}; + +table! { + temperature_breach (id) { + id -> Text, + duration -> Integer, + #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, + sensor_id -> Text, + location_id -> Nullable, + store_id -> Nullable, + start_timestamp -> Timestamp, + end_timestamp -> Timestamp, + acknowledged -> Bool, + threshold_minimum -> Float, + threshold_maximum -> Float, + threshold_duration -> Integer, + } +} + +table! { + #[sql_name = "temperature_breach"] + temperature_breach_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_breach -> sensor (sensor_id)); +joinable!(temperature_breach -> store (store_id)); +joinable!(temperature_breach -> location (location_id)); + +#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[DbValueStyle = "SCREAMING_SNAKE_CASE"] +pub enum TemperatureBreachRowType { + ColdConsecutive, + ColdCumulative, + HotConsecutive, + HotCumulative, +} + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_breach"] +pub struct TemperatureBreachRow { + pub id: String, + pub duration: i32, + #[column_name = "type_"] + pub r#type: TemperatureBreachRowType, + pub sensor_id: String, + pub location_id: Option, + pub store_id: Option, + pub start_timestamp: NaiveDateTime, + pub end_timestamp: NaiveDateTime, + pub acknowledged: bool, + pub threshold_minimum: f32, + pub threshold_maximum: f32, + pub threshold_duration: i32, +} + +impl Default for TemperatureBreachRow { + fn default() -> Self { + TemperatureBreachRow { + id: Default::default(), + duration: Default::default(), + r#type: TemperatureBreachRowType::HotConsecutive, + sensor_id: Default::default(), + location_id: None, + store_id: None, + start_timestamp: Default::default(), + end_timestamp: Default::default(), + acknowledged: false, + threshold_minimum: Default::default(), + threshold_maximum: Default::default(), + threshold_duration: Default::default(), + } + } +} +pub struct TemperatureBreachRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_breach_dsl::temperature_breach) + .values(row) + .on_conflict(temperature_breach_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_breach_dsl::temperature_breach) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { + let result = temperature_breach_dsl::temperature_breach + .filter(temperature_breach_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { + Ok(temperature_breach_dsl::temperature_breach + .filter(temperature_breach_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} From bc150945f4b3e138c21d4d7a8d0945e5f4c884ca Mon Sep 17 00:00:00 2001 From: adrianwb Date: Wed, 23 Aug 2023 17:51:44 +0100 Subject: [PATCH 03/10] Added timestamp filter for temperature_log --- .../repository/src/db_diesel/temperature_log.rs | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/server/repository/src/db_diesel/temperature_log.rs b/server/repository/src/db_diesel/temperature_log.rs index 064b8f091a..c7196df3bd 100644 --- a/server/repository/src/db_diesel/temperature_log.rs +++ b/server/repository/src/db_diesel/temperature_log.rs @@ -5,11 +5,11 @@ use super::{ use diesel::prelude::*; use crate::{ - diesel_macros::{apply_equal_filter, apply_sort_no_case}, + diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, repository_error::RepositoryError, }; -use crate::{EqualFilter, Pagination, Sort}; +use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; #[derive(PartialEq, Debug, Clone)] pub struct TemperatureLog { @@ -21,6 +21,7 @@ pub struct TemperatureLogFilter { pub id: Option>, pub sensor_id: Option>, pub store_id: Option>, + pub timestamp: Option, } #[derive(PartialEq, Debug)] @@ -63,10 +64,10 @@ impl<'a> TemperatureLogRepository<'a> { apply_sort_no_case!(query, sort, temperature_log_dsl::id) } TemperatureLogSortField::Timestamp => { - apply_sort_no_case!(query, sort, temperature_log_dsl::timestamp) + apply_sort!(query, sort, temperature_log_dsl::timestamp) } TemperatureLogSortField::Temperature => { - apply_sort_no_case!(query, sort, temperature_log_dsl::temperature) + apply_sort!(query, sort, temperature_log_dsl::temperature) } } } else { @@ -91,6 +92,7 @@ fn create_filtered_query(filter: Option) -> BoxedLogQuery apply_equal_filter!(query, filter.id, temperature_log_dsl::id); apply_equal_filter!(query, filter.sensor_id, temperature_log_dsl::sensor_id); apply_equal_filter!(query, filter.store_id, temperature_log_dsl::store_id); + apply_date_time_filter!(query, filter.timestamp, temperature_log_dsl::timestamp); } query @@ -106,6 +108,7 @@ impl TemperatureLogFilter { id: None, sensor_id: None, store_id: None, + timestamp: None, } } @@ -118,4 +121,9 @@ impl TemperatureLogFilter { self.store_id = Some(filter); self } + + pub fn timestamp(mut self, filter: DatetimeFilter) -> Self { + self.timestamp = Some(filter); + self + } } From aa52c3f8406ee3f98a95b01050d5875195b06517 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Thu, 24 Aug 2023 14:22:27 +0100 Subject: [PATCH 04/10] Add missing id filter --- server/repository/src/db_diesel/temperature_breach.rs | 5 +++++ server/repository/src/db_diesel/temperature_log.rs | 5 +++++ 2 files changed, 10 insertions(+) diff --git a/server/repository/src/db_diesel/temperature_breach.rs b/server/repository/src/db_diesel/temperature_breach.rs index f62778deb0..21064a2933 100644 --- a/server/repository/src/db_diesel/temperature_breach.rs +++ b/server/repository/src/db_diesel/temperature_breach.rs @@ -133,6 +133,11 @@ impl TemperatureBreachFilter { } } + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { self.sensor_id = Some(filter); self diff --git a/server/repository/src/db_diesel/temperature_log.rs b/server/repository/src/db_diesel/temperature_log.rs index c7196df3bd..be6ac43f76 100644 --- a/server/repository/src/db_diesel/temperature_log.rs +++ b/server/repository/src/db_diesel/temperature_log.rs @@ -112,6 +112,11 @@ impl TemperatureLogFilter { } } + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { self.sensor_id = Some(filter); self From 48adadfded69d2b52a854cd4e2e0e167525807af Mon Sep 17 00:00:00 2001 From: adrianwb Date: Thu, 24 Aug 2023 14:32:26 +0100 Subject: [PATCH 05/10] Add schema for temperature_breach_config --- .../repository/src/db_diesel/diesel_schema.rs | 3 +- server/repository/src/db_diesel/mod.rs | 4 + .../db_diesel/temperature_breach_config.rs | 134 ++++++++++++++++++ .../temperature_breach_config_row.rs | 107 ++++++++++++++ 4 files changed, 247 insertions(+), 1 deletion(-) create mode 100644 server/repository/src/db_diesel/temperature_breach_config.rs create mode 100644 server/repository/src/db_diesel/temperature_breach_config_row.rs diff --git a/server/repository/src/db_diesel/diesel_schema.rs b/server/repository/src/db_diesel/diesel_schema.rs index 8bf050898c..703e5ce9bd 100644 --- a/server/repository/src/db_diesel/diesel_schema.rs +++ b/server/repository/src/db_diesel/diesel_schema.rs @@ -10,7 +10,7 @@ use super::{ program_requisition::program_requisition_settings_row::program_requisition_settings, requisition_line_row::requisition_line, requisition_row::requisition, sensor_row::sensor, stock_line_row::stock_line, stocktake_line_row::stocktake_line, stocktake_row::stocktake, - store_row::store, temperature_breach_row::temperature_breach, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, + store_row::store, temperature_breach_config_row::temperature_breach_config, temperature_breach_row::temperature_breach, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, }; allow_tables_to_appear_in_same_query!( @@ -19,6 +19,7 @@ allow_tables_to_appear_in_same_query!( sensor, temperature_log, temperature_breach, + temperature_breach_config, item, stock_line, name, diff --git a/server/repository/src/db_diesel/mod.rs b/server/repository/src/db_diesel/mod.rs index 493e00267b..c682bd43a4 100644 --- a/server/repository/src/db_diesel/mod.rs +++ b/server/repository/src/db_diesel/mod.rs @@ -74,6 +74,8 @@ mod sync_buffer; mod sync_log; mod sync_log_row; mod temperature_breach; +mod temperature_breach_config; +mod temperature_breach_config_row; mod temperature_breach_row; mod temperature_log; mod temperature_log_row; @@ -151,6 +153,8 @@ pub use sync_buffer::*; pub use sync_log::*; pub use sync_log_row::*; pub use temperature_breach::*; +pub use temperature_breach_config::*; +pub use temperature_breach_config_row::*; pub use temperature_breach_row::*; pub use temperature_log::*; pub use temperature_log_row::*; diff --git a/server/repository/src/db_diesel/temperature_breach_config.rs b/server/repository/src/db_diesel/temperature_breach_config.rs new file mode 100644 index 0000000000..df3bfe79dc --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_config.rs @@ -0,0 +1,134 @@ +use super::{ + temperature_breach_config_row::{temperature_breach_config, temperature_breach_config::dsl as temperature_breach_config_dsl}, + DBType, TemperatureBreachConfigRow, TemperatureBreachRowType, StorageConnection, +}; +use diesel::prelude::*; + +use crate::{ + diesel_macros::{apply_equal_filter, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureBreachConfig { + pub temperature_breach_config_row: TemperatureBreachConfigRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureBreachConfigFilter { + pub id: Option>, + pub r#type: Option>, + pub is_active: Option, + pub store_id: Option>, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureBreachConfigSortField { + Id, + Description, +} + +pub type TemperatureBreachConfigSort = Sort; + +pub struct TemperatureBreachConfigRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachConfigRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachConfigRepository { connection } + } + + pub fn count(&self, filter: Option) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter(&self, filter: TemperatureBreachConfigFilter) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureBreachConfigSortField::Id => { + apply_sort_no_case!(query, sort, temperature_breach_config_dsl::id) + } + TemperatureBreachConfigSortField::Description => { + apply_sort_no_case!(query, sort, temperature_breach_config_dsl::description) + } + } + } else { + query = query.order(temperature_breach_config_dsl::description.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_breach_config::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_breach_config::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_breach_config_dsl::id); + apply_equal_filter!(query, filter.r#type, temperature_breach_config_dsl::type_); + + if let Some(value) = filter.is_active { + query = query.filter(temperature_breach_config_dsl::is_active.eq(value)); + } + + apply_equal_filter!(query, filter.store_id, temperature_breach_config_dsl::store_id); + } + + query +} + +pub fn to_domain(temperature_breach_config_row: TemperatureBreachConfigRow) -> TemperatureBreachConfig { + TemperatureBreachConfig { temperature_breach_config_row } +} + +impl TemperatureBreachConfigFilter { + pub fn new() -> TemperatureBreachConfigFilter { + TemperatureBreachConfigFilter { + id: None, + is_active: None, + r#type: None, + store_id: None, + } + } + + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + + pub fn is_active(mut self, filter: bool) -> Self { + self.is_active = Some(filter); + self + } + + pub fn r#type(mut self, filter: EqualFilter) -> Self { + self.r#type = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_breach_config_row.rs b/server/repository/src/db_diesel/temperature_breach_config_row.rs new file mode 100644 index 0000000000..a610c7f269 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_config_row.rs @@ -0,0 +1,107 @@ +use super::{ + temperature_breach_row::TemperatureBreachRowType, temperature_breach_config_row::temperature_breach_config::dsl as temperature_breach_config_dsl, store_row::store, + StorageConnection, +}; + +use crate::repository_error::RepositoryError; +use diesel::prelude::*; + +table! { + temperature_breach_config (id) { + id -> Text, + duration -> Integer, + #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, + description -> Text, + is_active -> Bool, + store_id -> Nullable, + minimum_temperature -> Float, + maximum_temperature -> Float, + } +} + +table! { + #[sql_name = "temperature_breach_config"] + temperature_breach_config_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_breach_config -> store (store_id)); + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_breach_config"] +pub struct TemperatureBreachConfigRow { + pub id: String, + pub duration: i32, + #[column_name = "type_"] + pub r#type: TemperatureBreachRowType, + pub description: String, + pub is_active: bool, + pub store_id: Option, + pub minimum_temperature: f32, + pub maximum_temperature: f32, +} + +impl Default for TemperatureBreachConfigRow { + fn default() -> Self { + TemperatureBreachConfigRow { + id: Default::default(), + duration: Default::default(), + r#type: TemperatureBreachRowType::HotConsecutive, + description: Default::default(), + is_active: false, + store_id: None, + minimum_temperature: Default::default(), + maximum_temperature: Default::default(), + } + } +} +pub struct TemperatureBreachConfigRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachConfigRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachConfigRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_breach_config_dsl::temperature_breach_config) + .values(row) + .on_conflict(temperature_breach_config_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_breach_config_dsl::temperature_breach_config) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { + let result = temperature_breach_config_dsl::temperature_breach_config + .filter(temperature_breach_config_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { + Ok(temperature_breach_config_dsl::temperature_breach_config + .filter(temperature_breach_config_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} From afd808ed91f01752d788c7e5b8451a9090ea7095 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Thu, 24 Aug 2023 14:34:57 +0100 Subject: [PATCH 06/10] After cargo fmt --- .../repository/src/db_diesel/diesel_schema.rs | 4 +- .../src/db_diesel/temperature_breach.rs | 345 +++++++++--------- .../db_diesel/temperature_breach_config.rs | 284 +++++++------- .../temperature_breach_config_row.rs | 221 +++++------ .../src/db_diesel/temperature_breach_row.rs | 276 +++++++------- .../src/db_diesel/temperature_log.rs | 273 +++++++------- .../src/db_diesel/temperature_log_row.rs | 211 +++++------ 7 files changed, 834 insertions(+), 780 deletions(-) diff --git a/server/repository/src/db_diesel/diesel_schema.rs b/server/repository/src/db_diesel/diesel_schema.rs index 703e5ce9bd..39eeeec101 100644 --- a/server/repository/src/db_diesel/diesel_schema.rs +++ b/server/repository/src/db_diesel/diesel_schema.rs @@ -10,7 +10,9 @@ use super::{ program_requisition::program_requisition_settings_row::program_requisition_settings, requisition_line_row::requisition_line, requisition_row::requisition, sensor_row::sensor, stock_line_row::stock_line, stocktake_line_row::stocktake_line, stocktake_row::stocktake, - store_row::store, temperature_breach_config_row::temperature_breach_config, temperature_breach_row::temperature_breach, temperature_log_row::temperature_log, unit_row::unit, user_row::user_account, + store_row::store, temperature_breach_config_row::temperature_breach_config, + temperature_breach_row::temperature_breach, temperature_log_row::temperature_log, + unit_row::unit, user_row::user_account, }; allow_tables_to_appear_in_same_query!( diff --git a/server/repository/src/db_diesel/temperature_breach.rs b/server/repository/src/db_diesel/temperature_breach.rs index 21064a2933..656ef021be 100644 --- a/server/repository/src/db_diesel/temperature_breach.rs +++ b/server/repository/src/db_diesel/temperature_breach.rs @@ -1,165 +1,180 @@ -use super::{ - temperature_breach_row::{temperature_breach, temperature_breach::dsl as temperature_breach_dsl}, - DBType, TemperatureBreachRow, TemperatureBreachRowType, StorageConnection, -}; -use diesel::prelude::*; -use util::inline_init; - -use crate::{ - diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, - repository_error::RepositoryError, -}; - -use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; - -#[derive(PartialEq, Debug, Clone)] -pub struct TemperatureBreach { - pub temperature_breach_row: TemperatureBreachRow, -} - -#[derive(Clone, PartialEq, Debug)] -pub struct TemperatureBreachFilter { - pub id: Option>, - pub r#type: Option>, - pub sensor_id: Option>, - pub store_id: Option>, - pub start_timestamp: Option, - pub end_timestamp: Option, -} - -#[derive(PartialEq, Debug)] -pub enum TemperatureBreachSortField { - Id, - StartTimestamp, - EndTimestamp, -} - -pub type TemperatureBreachSort = Sort; - -pub struct TemperatureBreachRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureBreachRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureBreachRepository { connection } - } - - pub fn count(&self, filter: Option) -> Result { - let query = create_filtered_query(filter); - Ok(query.count().get_result(&self.connection.connection)?) - } - - pub fn query_by_filter(&self, filter: TemperatureBreachFilter) -> Result, RepositoryError> { - self.query(Pagination::all(), Some(filter), None) - } - - pub fn query( - &self, - pagination: Pagination, - filter: Option, - sort: Option, - ) -> Result, RepositoryError> { - let mut query = create_filtered_query(filter); - if let Some(sort) = sort { - match sort.key { - TemperatureBreachSortField::Id => { - apply_sort_no_case!(query, sort, temperature_breach_dsl::id) - } - TemperatureBreachSortField::StartTimestamp => { - apply_sort!(query, sort, temperature_breach_dsl::start_timestamp) - } - TemperatureBreachSortField::EndTimestamp => { - apply_sort!(query, sort, temperature_breach_dsl::end_timestamp) - } - } - } else { - query = query.order(temperature_breach_dsl::start_timestamp.asc()) - } - - let result = query - .offset(pagination.offset as i64) - .limit(pagination.limit as i64) - .load::(&self.connection.connection)?; - - Ok(result.into_iter().map(to_domain).collect()) - } -} - -type BoxedLogQuery = temperature_breach::BoxedQuery<'static, DBType>; - -fn create_filtered_query(filter: Option) -> BoxedLogQuery { - let mut query = temperature_breach::table.into_boxed(); - - if let Some(filter) = filter { - apply_equal_filter!(query, filter.id, temperature_breach_dsl::id); - apply_equal_filter!(query, filter.sensor_id, temperature_breach_dsl::sensor_id); - apply_equal_filter!(query, filter.store_id, temperature_breach_dsl::store_id); - apply_equal_filter!(query, filter.r#type, temperature_breach_dsl::type_); - apply_date_time_filter!(query, filter.start_timestamp, temperature_breach_dsl::start_timestamp); - apply_date_time_filter!(query, filter.end_timestamp, temperature_breach_dsl::end_timestamp); - } - - query -} - -impl TemperatureBreachRowType { - pub fn equal_to(&self) -> EqualFilter { - inline_init(|r: &mut EqualFilter| r.equal_to = Some(self.clone())) - } - - pub fn not_equal_to(&self) -> EqualFilter { - inline_init(|r: &mut EqualFilter| r.not_equal_to = Some(self.clone())) - } - - pub fn equal_any(value: Vec) -> EqualFilter { - inline_init(|r: &mut EqualFilter| r.equal_any = Some(value)) - } -} - -pub fn to_domain(temperature_breach_row: TemperatureBreachRow) -> TemperatureBreach { - TemperatureBreach { temperature_breach_row } -} - -impl TemperatureBreachFilter { - pub fn new() -> TemperatureBreachFilter { - TemperatureBreachFilter { - id: None, - sensor_id: None, - store_id: None, - start_timestamp: None, - end_timestamp: None, - r#type: None, - } - } - - pub fn id(mut self, filter: EqualFilter) -> Self { - self.id = Some(filter); - self - } - - pub fn sensor_id(mut self, filter: EqualFilter) -> Self { - self.sensor_id = Some(filter); - self - } - - pub fn store_id(mut self, filter: EqualFilter) -> Self { - self.store_id = Some(filter); - self - } - - pub fn start_timestamp(mut self, filter: DatetimeFilter) -> Self { - self.start_timestamp = Some(filter); - self - } - - pub fn end_timestamp(mut self, filter: DatetimeFilter) -> Self { - self.end_timestamp = Some(filter); - self - } - - pub fn r#type(mut self, filter: EqualFilter) -> Self { - self.r#type = Some(filter); - self - } -} +use super::{ + temperature_breach_row::{ + temperature_breach, temperature_breach::dsl as temperature_breach_dsl, + }, + DBType, StorageConnection, TemperatureBreachRow, TemperatureBreachRowType, +}; +use diesel::prelude::*; +use util::inline_init; + +use crate::{ + diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureBreach { + pub temperature_breach_row: TemperatureBreachRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureBreachFilter { + pub id: Option>, + pub r#type: Option>, + pub sensor_id: Option>, + pub store_id: Option>, + pub start_timestamp: Option, + pub end_timestamp: Option, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureBreachSortField { + Id, + StartTimestamp, + EndTimestamp, +} + +pub type TemperatureBreachSort = Sort; + +pub struct TemperatureBreachRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachRepository { connection } + } + + pub fn count(&self, filter: Option) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter( + &self, + filter: TemperatureBreachFilter, + ) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureBreachSortField::Id => { + apply_sort_no_case!(query, sort, temperature_breach_dsl::id) + } + TemperatureBreachSortField::StartTimestamp => { + apply_sort!(query, sort, temperature_breach_dsl::start_timestamp) + } + TemperatureBreachSortField::EndTimestamp => { + apply_sort!(query, sort, temperature_breach_dsl::end_timestamp) + } + } + } else { + query = query.order(temperature_breach_dsl::start_timestamp.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_breach::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_breach::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_breach_dsl::id); + apply_equal_filter!(query, filter.sensor_id, temperature_breach_dsl::sensor_id); + apply_equal_filter!(query, filter.store_id, temperature_breach_dsl::store_id); + apply_equal_filter!(query, filter.r#type, temperature_breach_dsl::type_); + apply_date_time_filter!( + query, + filter.start_timestamp, + temperature_breach_dsl::start_timestamp + ); + apply_date_time_filter!( + query, + filter.end_timestamp, + temperature_breach_dsl::end_timestamp + ); + } + + query +} + +impl TemperatureBreachRowType { + pub fn equal_to(&self) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.equal_to = Some(self.clone())) + } + + pub fn not_equal_to(&self) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.not_equal_to = Some(self.clone())) + } + + pub fn equal_any(value: Vec) -> EqualFilter { + inline_init(|r: &mut EqualFilter| r.equal_any = Some(value)) + } +} + +pub fn to_domain(temperature_breach_row: TemperatureBreachRow) -> TemperatureBreach { + TemperatureBreach { + temperature_breach_row, + } +} + +impl TemperatureBreachFilter { + pub fn new() -> TemperatureBreachFilter { + TemperatureBreachFilter { + id: None, + sensor_id: None, + store_id: None, + start_timestamp: None, + end_timestamp: None, + r#type: None, + } + } + + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { + self.sensor_id = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } + + pub fn start_timestamp(mut self, filter: DatetimeFilter) -> Self { + self.start_timestamp = Some(filter); + self + } + + pub fn end_timestamp(mut self, filter: DatetimeFilter) -> Self { + self.end_timestamp = Some(filter); + self + } + + pub fn r#type(mut self, filter: EqualFilter) -> Self { + self.r#type = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_breach_config.rs b/server/repository/src/db_diesel/temperature_breach_config.rs index df3bfe79dc..88c0f933e4 100644 --- a/server/repository/src/db_diesel/temperature_breach_config.rs +++ b/server/repository/src/db_diesel/temperature_breach_config.rs @@ -1,134 +1,150 @@ -use super::{ - temperature_breach_config_row::{temperature_breach_config, temperature_breach_config::dsl as temperature_breach_config_dsl}, - DBType, TemperatureBreachConfigRow, TemperatureBreachRowType, StorageConnection, -}; -use diesel::prelude::*; - -use crate::{ - diesel_macros::{apply_equal_filter, apply_sort_no_case}, - repository_error::RepositoryError, -}; - -use crate::{EqualFilter, Pagination, Sort}; - -#[derive(PartialEq, Debug, Clone)] -pub struct TemperatureBreachConfig { - pub temperature_breach_config_row: TemperatureBreachConfigRow, -} - -#[derive(Clone, PartialEq, Debug)] -pub struct TemperatureBreachConfigFilter { - pub id: Option>, - pub r#type: Option>, - pub is_active: Option, - pub store_id: Option>, -} - -#[derive(PartialEq, Debug)] -pub enum TemperatureBreachConfigSortField { - Id, - Description, -} - -pub type TemperatureBreachConfigSort = Sort; - -pub struct TemperatureBreachConfigRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureBreachConfigRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureBreachConfigRepository { connection } - } - - pub fn count(&self, filter: Option) -> Result { - let query = create_filtered_query(filter); - Ok(query.count().get_result(&self.connection.connection)?) - } - - pub fn query_by_filter(&self, filter: TemperatureBreachConfigFilter) -> Result, RepositoryError> { - self.query(Pagination::all(), Some(filter), None) - } - - pub fn query( - &self, - pagination: Pagination, - filter: Option, - sort: Option, - ) -> Result, RepositoryError> { - let mut query = create_filtered_query(filter); - if let Some(sort) = sort { - match sort.key { - TemperatureBreachConfigSortField::Id => { - apply_sort_no_case!(query, sort, temperature_breach_config_dsl::id) - } - TemperatureBreachConfigSortField::Description => { - apply_sort_no_case!(query, sort, temperature_breach_config_dsl::description) - } - } - } else { - query = query.order(temperature_breach_config_dsl::description.asc()) - } - - let result = query - .offset(pagination.offset as i64) - .limit(pagination.limit as i64) - .load::(&self.connection.connection)?; - - Ok(result.into_iter().map(to_domain).collect()) - } -} - -type BoxedLogQuery = temperature_breach_config::BoxedQuery<'static, DBType>; - -fn create_filtered_query(filter: Option) -> BoxedLogQuery { - let mut query = temperature_breach_config::table.into_boxed(); - - if let Some(filter) = filter { - apply_equal_filter!(query, filter.id, temperature_breach_config_dsl::id); - apply_equal_filter!(query, filter.r#type, temperature_breach_config_dsl::type_); - - if let Some(value) = filter.is_active { - query = query.filter(temperature_breach_config_dsl::is_active.eq(value)); - } - - apply_equal_filter!(query, filter.store_id, temperature_breach_config_dsl::store_id); - } - - query -} - -pub fn to_domain(temperature_breach_config_row: TemperatureBreachConfigRow) -> TemperatureBreachConfig { - TemperatureBreachConfig { temperature_breach_config_row } -} - -impl TemperatureBreachConfigFilter { - pub fn new() -> TemperatureBreachConfigFilter { - TemperatureBreachConfigFilter { - id: None, - is_active: None, - r#type: None, - store_id: None, - } - } - - pub fn id(mut self, filter: EqualFilter) -> Self { - self.id = Some(filter); - self - } - - pub fn is_active(mut self, filter: bool) -> Self { - self.is_active = Some(filter); - self - } - - pub fn r#type(mut self, filter: EqualFilter) -> Self { - self.r#type = Some(filter); - self - } - - pub fn store_id(mut self, filter: EqualFilter) -> Self { - self.store_id = Some(filter); - self - } -} +use super::{ + temperature_breach_config_row::{ + temperature_breach_config, temperature_breach_config::dsl as temperature_breach_config_dsl, + }, + DBType, StorageConnection, TemperatureBreachConfigRow, TemperatureBreachRowType, +}; +use diesel::prelude::*; + +use crate::{ + diesel_macros::{apply_equal_filter, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureBreachConfig { + pub temperature_breach_config_row: TemperatureBreachConfigRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureBreachConfigFilter { + pub id: Option>, + pub r#type: Option>, + pub is_active: Option, + pub store_id: Option>, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureBreachConfigSortField { + Id, + Description, +} + +pub type TemperatureBreachConfigSort = Sort; + +pub struct TemperatureBreachConfigRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachConfigRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachConfigRepository { connection } + } + + pub fn count( + &self, + filter: Option, + ) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter( + &self, + filter: TemperatureBreachConfigFilter, + ) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureBreachConfigSortField::Id => { + apply_sort_no_case!(query, sort, temperature_breach_config_dsl::id) + } + TemperatureBreachConfigSortField::Description => { + apply_sort_no_case!(query, sort, temperature_breach_config_dsl::description) + } + } + } else { + query = query.order(temperature_breach_config_dsl::description.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_breach_config::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_breach_config::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_breach_config_dsl::id); + apply_equal_filter!(query, filter.r#type, temperature_breach_config_dsl::type_); + + if let Some(value) = filter.is_active { + query = query.filter(temperature_breach_config_dsl::is_active.eq(value)); + } + + apply_equal_filter!( + query, + filter.store_id, + temperature_breach_config_dsl::store_id + ); + } + + query +} + +pub fn to_domain( + temperature_breach_config_row: TemperatureBreachConfigRow, +) -> TemperatureBreachConfig { + TemperatureBreachConfig { + temperature_breach_config_row, + } +} + +impl TemperatureBreachConfigFilter { + pub fn new() -> TemperatureBreachConfigFilter { + TemperatureBreachConfigFilter { + id: None, + is_active: None, + r#type: None, + store_id: None, + } + } + + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + + pub fn is_active(mut self, filter: bool) -> Self { + self.is_active = Some(filter); + self + } + + pub fn r#type(mut self, filter: EqualFilter) -> Self { + self.r#type = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_breach_config_row.rs b/server/repository/src/db_diesel/temperature_breach_config_row.rs index a610c7f269..8c99feea5c 100644 --- a/server/repository/src/db_diesel/temperature_breach_config_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_config_row.rs @@ -1,107 +1,114 @@ -use super::{ - temperature_breach_row::TemperatureBreachRowType, temperature_breach_config_row::temperature_breach_config::dsl as temperature_breach_config_dsl, store_row::store, - StorageConnection, -}; - -use crate::repository_error::RepositoryError; -use diesel::prelude::*; - -table! { - temperature_breach_config (id) { - id -> Text, - duration -> Integer, - #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, - description -> Text, - is_active -> Bool, - store_id -> Nullable, - minimum_temperature -> Float, - maximum_temperature -> Float, - } -} - -table! { - #[sql_name = "temperature_breach_config"] - temperature_breach_config_is_sync_update (id) { - id -> Text, - is_sync_update -> Bool, - } -} - -joinable!(temperature_breach_config -> store (store_id)); - -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] -#[changeset_options(treat_none_as_null = "true")] -#[table_name = "temperature_breach_config"] -pub struct TemperatureBreachConfigRow { - pub id: String, - pub duration: i32, - #[column_name = "type_"] - pub r#type: TemperatureBreachRowType, - pub description: String, - pub is_active: bool, - pub store_id: Option, - pub minimum_temperature: f32, - pub maximum_temperature: f32, -} - -impl Default for TemperatureBreachConfigRow { - fn default() -> Self { - TemperatureBreachConfigRow { - id: Default::default(), - duration: Default::default(), - r#type: TemperatureBreachRowType::HotConsecutive, - description: Default::default(), - is_active: false, - store_id: None, - minimum_temperature: Default::default(), - maximum_temperature: Default::default(), - } - } -} -pub struct TemperatureBreachConfigRowRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureBreachConfigRowRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureBreachConfigRowRepository { connection } - } - - #[cfg(feature = "postgres")] - pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { - diesel::insert_into(temperature_breach_config_dsl::temperature_breach_config) - .values(row) - .on_conflict(temperature_breach_config_dsl::id) - .do_update() - .set(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - #[cfg(not(feature = "postgres"))] - pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { - diesel::replace_into(temperature_breach_config_dsl::temperature_breach_config) - .values(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - pub fn upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { - self._upsert_one(row)?; - Ok(()) - } - - pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { - let result = temperature_breach_config_dsl::temperature_breach_config - .filter(temperature_breach_config_dsl::id.eq(id)) - .first(&self.connection.connection) - .optional()?; - Ok(result) - } - - pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { - Ok(temperature_breach_config_dsl::temperature_breach_config - .filter(temperature_breach_config_dsl::id.eq_any(ids)) - .load(&self.connection.connection)?) - } -} +use super::{ + store_row::store, + temperature_breach_config_row::temperature_breach_config::dsl as temperature_breach_config_dsl, + temperature_breach_row::TemperatureBreachRowType, StorageConnection, +}; + +use crate::repository_error::RepositoryError; +use diesel::prelude::*; + +table! { + temperature_breach_config (id) { + id -> Text, + duration -> Integer, + #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, + description -> Text, + is_active -> Bool, + store_id -> Nullable, + minimum_temperature -> Float, + maximum_temperature -> Float, + } +} + +table! { + #[sql_name = "temperature_breach_config"] + temperature_breach_config_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_breach_config -> store (store_id)); + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_breach_config"] +pub struct TemperatureBreachConfigRow { + pub id: String, + pub duration: i32, + #[column_name = "type_"] + pub r#type: TemperatureBreachRowType, + pub description: String, + pub is_active: bool, + pub store_id: Option, + pub minimum_temperature: f32, + pub maximum_temperature: f32, +} + +impl Default for TemperatureBreachConfigRow { + fn default() -> Self { + TemperatureBreachConfigRow { + id: Default::default(), + duration: Default::default(), + r#type: TemperatureBreachRowType::HotConsecutive, + description: Default::default(), + is_active: false, + store_id: None, + minimum_temperature: Default::default(), + maximum_temperature: Default::default(), + } + } +} +pub struct TemperatureBreachConfigRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachConfigRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachConfigRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_breach_config_dsl::temperature_breach_config) + .values(row) + .on_conflict(temperature_breach_config_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_breach_config_dsl::temperature_breach_config) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureBreachConfigRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id( + &self, + id: &str, + ) -> Result, RepositoryError> { + let result = temperature_breach_config_dsl::temperature_breach_config + .filter(temperature_breach_config_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id( + &self, + ids: &[String], + ) -> Result, RepositoryError> { + Ok(temperature_breach_config_dsl::temperature_breach_config + .filter(temperature_breach_config_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} diff --git a/server/repository/src/db_diesel/temperature_breach_row.rs b/server/repository/src/db_diesel/temperature_breach_row.rs index 76d195c2df..99f3f1e485 100644 --- a/server/repository/src/db_diesel/temperature_breach_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_row.rs @@ -1,135 +1,141 @@ -use super::{ - location_row::location, sensor_row::sensor, temperature_breach_row::temperature_breach::dsl as temperature_breach_dsl, store_row::store, - StorageConnection, -}; - -use crate::repository_error::RepositoryError; - -use chrono::NaiveDateTime; -use diesel::prelude::*; -use diesel_derive_enum::DbEnum; -use serde::{Deserialize, Serialize}; - -table! { - temperature_breach (id) { - id -> Text, - duration -> Integer, - #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, - sensor_id -> Text, - location_id -> Nullable, - store_id -> Nullable, - start_timestamp -> Timestamp, - end_timestamp -> Timestamp, - acknowledged -> Bool, - threshold_minimum -> Float, - threshold_maximum -> Float, - threshold_duration -> Integer, - } -} - -table! { - #[sql_name = "temperature_breach"] - temperature_breach_is_sync_update (id) { - id -> Text, - is_sync_update -> Bool, - } -} - -joinable!(temperature_breach -> sensor (sensor_id)); -joinable!(temperature_breach -> store (store_id)); -joinable!(temperature_breach -> location (location_id)); - -#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] -#[serde(rename_all = "SCREAMING_SNAKE_CASE")] -#[DbValueStyle = "SCREAMING_SNAKE_CASE"] -pub enum TemperatureBreachRowType { - ColdConsecutive, - ColdCumulative, - HotConsecutive, - HotCumulative, -} - -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] -#[changeset_options(treat_none_as_null = "true")] -#[table_name = "temperature_breach"] -pub struct TemperatureBreachRow { - pub id: String, - pub duration: i32, - #[column_name = "type_"] - pub r#type: TemperatureBreachRowType, - pub sensor_id: String, - pub location_id: Option, - pub store_id: Option, - pub start_timestamp: NaiveDateTime, - pub end_timestamp: NaiveDateTime, - pub acknowledged: bool, - pub threshold_minimum: f32, - pub threshold_maximum: f32, - pub threshold_duration: i32, -} - -impl Default for TemperatureBreachRow { - fn default() -> Self { - TemperatureBreachRow { - id: Default::default(), - duration: Default::default(), - r#type: TemperatureBreachRowType::HotConsecutive, - sensor_id: Default::default(), - location_id: None, - store_id: None, - start_timestamp: Default::default(), - end_timestamp: Default::default(), - acknowledged: false, - threshold_minimum: Default::default(), - threshold_maximum: Default::default(), - threshold_duration: Default::default(), - } - } -} -pub struct TemperatureBreachRowRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureBreachRowRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureBreachRowRepository { connection } - } - - #[cfg(feature = "postgres")] - pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { - diesel::insert_into(temperature_breach_dsl::temperature_breach) - .values(row) - .on_conflict(temperature_breach_dsl::id) - .do_update() - .set(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - #[cfg(not(feature = "postgres"))] - pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { - diesel::replace_into(temperature_breach_dsl::temperature_breach) - .values(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - pub fn upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { - self._upsert_one(row)?; - Ok(()) - } - - pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { - let result = temperature_breach_dsl::temperature_breach - .filter(temperature_breach_dsl::id.eq(id)) - .first(&self.connection.connection) - .optional()?; - Ok(result) - } - - pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { - Ok(temperature_breach_dsl::temperature_breach - .filter(temperature_breach_dsl::id.eq_any(ids)) - .load(&self.connection.connection)?) - } -} +use super::{ + location_row::location, sensor_row::sensor, store_row::store, + temperature_breach_row::temperature_breach::dsl as temperature_breach_dsl, StorageConnection, +}; + +use crate::repository_error::RepositoryError; + +use chrono::NaiveDateTime; +use diesel::prelude::*; +use diesel_derive_enum::DbEnum; +use serde::{Deserialize, Serialize}; + +table! { + temperature_breach (id) { + id -> Text, + duration -> Integer, + #[sql_name = "type"] type_ -> crate::db_diesel::temperature_breach_row::TemperatureBreachRowTypeMapping, + sensor_id -> Text, + location_id -> Nullable, + store_id -> Nullable, + start_timestamp -> Timestamp, + end_timestamp -> Timestamp, + acknowledged -> Bool, + threshold_minimum -> Float, + threshold_maximum -> Float, + threshold_duration -> Integer, + } +} + +table! { + #[sql_name = "temperature_breach"] + temperature_breach_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_breach -> sensor (sensor_id)); +joinable!(temperature_breach -> store (store_id)); +joinable!(temperature_breach -> location (location_id)); + +#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[serde(rename_all = "SCREAMING_SNAKE_CASE")] +#[DbValueStyle = "SCREAMING_SNAKE_CASE"] +pub enum TemperatureBreachRowType { + ColdConsecutive, + ColdCumulative, + HotConsecutive, + HotCumulative, +} + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_breach"] +pub struct TemperatureBreachRow { + pub id: String, + pub duration: i32, + #[column_name = "type_"] + pub r#type: TemperatureBreachRowType, + pub sensor_id: String, + pub location_id: Option, + pub store_id: Option, + pub start_timestamp: NaiveDateTime, + pub end_timestamp: NaiveDateTime, + pub acknowledged: bool, + pub threshold_minimum: f32, + pub threshold_maximum: f32, + pub threshold_duration: i32, +} + +impl Default for TemperatureBreachRow { + fn default() -> Self { + TemperatureBreachRow { + id: Default::default(), + duration: Default::default(), + r#type: TemperatureBreachRowType::HotConsecutive, + sensor_id: Default::default(), + location_id: None, + store_id: None, + start_timestamp: Default::default(), + end_timestamp: Default::default(), + acknowledged: false, + threshold_minimum: Default::default(), + threshold_maximum: Default::default(), + threshold_duration: Default::default(), + } + } +} +pub struct TemperatureBreachRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureBreachRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureBreachRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_breach_dsl::temperature_breach) + .values(row) + .on_conflict(temperature_breach_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_breach_dsl::temperature_breach) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureBreachRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id( + &self, + id: &str, + ) -> Result, RepositoryError> { + let result = temperature_breach_dsl::temperature_breach + .filter(temperature_breach_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id( + &self, + ids: &[String], + ) -> Result, RepositoryError> { + Ok(temperature_breach_dsl::temperature_breach + .filter(temperature_breach_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} diff --git a/server/repository/src/db_diesel/temperature_log.rs b/server/repository/src/db_diesel/temperature_log.rs index be6ac43f76..50c02559a1 100644 --- a/server/repository/src/db_diesel/temperature_log.rs +++ b/server/repository/src/db_diesel/temperature_log.rs @@ -1,134 +1,139 @@ -use super::{ - temperature_log_row::{temperature_log, temperature_log::dsl as temperature_log_dsl}, - DBType, TemperatureLogRow, StorageConnection, -}; -use diesel::prelude::*; - -use crate::{ - diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, - repository_error::RepositoryError, -}; - -use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; - -#[derive(PartialEq, Debug, Clone)] -pub struct TemperatureLog { - pub temperature_log_row: TemperatureLogRow, -} - -#[derive(Clone, PartialEq, Debug)] -pub struct TemperatureLogFilter { - pub id: Option>, - pub sensor_id: Option>, - pub store_id: Option>, - pub timestamp: Option, -} - -#[derive(PartialEq, Debug)] -pub enum TemperatureLogSortField { - Id, - Timestamp, - Temperature, -} - -pub type TemperatureLogSort = Sort; - -pub struct TemperatureLogRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureLogRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureLogRepository { connection } - } - - pub fn count(&self, filter: Option) -> Result { - let query = create_filtered_query(filter); - Ok(query.count().get_result(&self.connection.connection)?) - } - - pub fn query_by_filter(&self, filter: TemperatureLogFilter) -> Result, RepositoryError> { - self.query(Pagination::all(), Some(filter), None) - } - - pub fn query( - &self, - pagination: Pagination, - filter: Option, - sort: Option, - ) -> Result, RepositoryError> { - let mut query = create_filtered_query(filter); - if let Some(sort) = sort { - match sort.key { - TemperatureLogSortField::Id => { - apply_sort_no_case!(query, sort, temperature_log_dsl::id) - } - TemperatureLogSortField::Timestamp => { - apply_sort!(query, sort, temperature_log_dsl::timestamp) - } - TemperatureLogSortField::Temperature => { - apply_sort!(query, sort, temperature_log_dsl::temperature) - } - } - } else { - query = query.order(temperature_log_dsl::timestamp.asc()) - } - - let result = query - .offset(pagination.offset as i64) - .limit(pagination.limit as i64) - .load::(&self.connection.connection)?; - - Ok(result.into_iter().map(to_domain).collect()) - } -} - -type BoxedLogQuery = temperature_log::BoxedQuery<'static, DBType>; - -fn create_filtered_query(filter: Option) -> BoxedLogQuery { - let mut query = temperature_log::table.into_boxed(); - - if let Some(filter) = filter { - apply_equal_filter!(query, filter.id, temperature_log_dsl::id); - apply_equal_filter!(query, filter.sensor_id, temperature_log_dsl::sensor_id); - apply_equal_filter!(query, filter.store_id, temperature_log_dsl::store_id); - apply_date_time_filter!(query, filter.timestamp, temperature_log_dsl::timestamp); - } - - query -} - -pub fn to_domain(temperature_log_row: TemperatureLogRow) -> TemperatureLog { - TemperatureLog { temperature_log_row } -} - -impl TemperatureLogFilter { - pub fn new() -> TemperatureLogFilter { - TemperatureLogFilter { - id: None, - sensor_id: None, - store_id: None, - timestamp: None, - } - } - - pub fn id(mut self, filter: EqualFilter) -> Self { - self.id = Some(filter); - self - } - - pub fn sensor_id(mut self, filter: EqualFilter) -> Self { - self.sensor_id = Some(filter); - self - } - - pub fn store_id(mut self, filter: EqualFilter) -> Self { - self.store_id = Some(filter); - self - } - - pub fn timestamp(mut self, filter: DatetimeFilter) -> Self { - self.timestamp = Some(filter); - self - } -} +use super::{ + temperature_log_row::{temperature_log, temperature_log::dsl as temperature_log_dsl}, + DBType, StorageConnection, TemperatureLogRow, +}; +use diesel::prelude::*; + +use crate::{ + diesel_macros::{apply_date_time_filter, apply_equal_filter, apply_sort, apply_sort_no_case}, + repository_error::RepositoryError, +}; + +use crate::{DatetimeFilter, EqualFilter, Pagination, Sort}; + +#[derive(PartialEq, Debug, Clone)] +pub struct TemperatureLog { + pub temperature_log_row: TemperatureLogRow, +} + +#[derive(Clone, PartialEq, Debug)] +pub struct TemperatureLogFilter { + pub id: Option>, + pub sensor_id: Option>, + pub store_id: Option>, + pub timestamp: Option, +} + +#[derive(PartialEq, Debug)] +pub enum TemperatureLogSortField { + Id, + Timestamp, + Temperature, +} + +pub type TemperatureLogSort = Sort; + +pub struct TemperatureLogRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureLogRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureLogRepository { connection } + } + + pub fn count(&self, filter: Option) -> Result { + let query = create_filtered_query(filter); + Ok(query.count().get_result(&self.connection.connection)?) + } + + pub fn query_by_filter( + &self, + filter: TemperatureLogFilter, + ) -> Result, RepositoryError> { + self.query(Pagination::all(), Some(filter), None) + } + + pub fn query( + &self, + pagination: Pagination, + filter: Option, + sort: Option, + ) -> Result, RepositoryError> { + let mut query = create_filtered_query(filter); + if let Some(sort) = sort { + match sort.key { + TemperatureLogSortField::Id => { + apply_sort_no_case!(query, sort, temperature_log_dsl::id) + } + TemperatureLogSortField::Timestamp => { + apply_sort!(query, sort, temperature_log_dsl::timestamp) + } + TemperatureLogSortField::Temperature => { + apply_sort!(query, sort, temperature_log_dsl::temperature) + } + } + } else { + query = query.order(temperature_log_dsl::timestamp.asc()) + } + + let result = query + .offset(pagination.offset as i64) + .limit(pagination.limit as i64) + .load::(&self.connection.connection)?; + + Ok(result.into_iter().map(to_domain).collect()) + } +} + +type BoxedLogQuery = temperature_log::BoxedQuery<'static, DBType>; + +fn create_filtered_query(filter: Option) -> BoxedLogQuery { + let mut query = temperature_log::table.into_boxed(); + + if let Some(filter) = filter { + apply_equal_filter!(query, filter.id, temperature_log_dsl::id); + apply_equal_filter!(query, filter.sensor_id, temperature_log_dsl::sensor_id); + apply_equal_filter!(query, filter.store_id, temperature_log_dsl::store_id); + apply_date_time_filter!(query, filter.timestamp, temperature_log_dsl::timestamp); + } + + query +} + +pub fn to_domain(temperature_log_row: TemperatureLogRow) -> TemperatureLog { + TemperatureLog { + temperature_log_row, + } +} + +impl TemperatureLogFilter { + pub fn new() -> TemperatureLogFilter { + TemperatureLogFilter { + id: None, + sensor_id: None, + store_id: None, + timestamp: None, + } + } + + pub fn id(mut self, filter: EqualFilter) -> Self { + self.id = Some(filter); + self + } + + pub fn sensor_id(mut self, filter: EqualFilter) -> Self { + self.sensor_id = Some(filter); + self + } + + pub fn store_id(mut self, filter: EqualFilter) -> Self { + self.store_id = Some(filter); + self + } + + pub fn timestamp(mut self, filter: DatetimeFilter) -> Self { + self.timestamp = Some(filter); + self + } +} diff --git a/server/repository/src/db_diesel/temperature_log_row.rs b/server/repository/src/db_diesel/temperature_log_row.rs index 6580c8aca4..5605323001 100644 --- a/server/repository/src/db_diesel/temperature_log_row.rs +++ b/server/repository/src/db_diesel/temperature_log_row.rs @@ -1,104 +1,107 @@ -use super::{ - location_row::location, sensor_row::sensor, temperature_log_row::temperature_log::dsl as temperature_log_dsl, store_row::store, - StorageConnection, -}; - -use crate::repository_error::RepositoryError; - -use chrono::NaiveDateTime; -use diesel::prelude::*; - -table! { - temperature_log (id) { - id -> Text, - temperature -> Float, - sensor_id -> Text, - location_id -> Nullable, - store_id -> Nullable, - timestamp -> Timestamp, - } -} - -table! { - #[sql_name = "temperature_log"] - temperature_log_is_sync_update (id) { - id -> Text, - is_sync_update -> Bool, - } -} - -joinable!(temperature_log -> sensor (sensor_id)); -joinable!(temperature_log -> store (store_id)); -joinable!(temperature_log -> location (location_id)); - -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] -#[changeset_options(treat_none_as_null = "true")] -#[table_name = "temperature_log"] -pub struct TemperatureLogRow { - pub id: String, - pub temperature: f32, - pub sensor_id: String, - pub location_id: Option, - pub store_id: Option, - pub timestamp: NaiveDateTime, -} - -impl Default for TemperatureLogRow { - fn default() -> Self { - TemperatureLogRow { - id: Default::default(), - temperature: Default::default(), - sensor_id: Default::default(), - location_id: None, - store_id: None, - timestamp: Default::default(), - } - } -} -pub struct TemperatureLogRowRepository<'a> { - connection: &'a StorageConnection, -} - -impl<'a> TemperatureLogRowRepository<'a> { - pub fn new(connection: &'a StorageConnection) -> Self { - TemperatureLogRowRepository { connection } - } - - #[cfg(feature = "postgres")] - pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { - diesel::insert_into(temperature_log_dsl::temperature_log) - .values(row) - .on_conflict(temperature_log_dsl::id) - .do_update() - .set(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - #[cfg(not(feature = "postgres"))] - pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { - diesel::replace_into(temperature_log_dsl::temperature_log) - .values(row) - .execute(&self.connection.connection)?; - Ok(()) - } - - pub fn upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { - self._upsert_one(row)?; - Ok(()) - } - - pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { - let result = temperature_log_dsl::temperature_log - .filter(temperature_log_dsl::id.eq(id)) - .first(&self.connection.connection) - .optional()?; - Ok(result) - } - - pub fn find_many_by_id(&self, ids: &[String]) -> Result, RepositoryError> { - Ok(temperature_log_dsl::temperature_log - .filter(temperature_log_dsl::id.eq_any(ids)) - .load(&self.connection.connection)?) - } -} +use super::{ + location_row::location, sensor_row::sensor, store_row::store, + temperature_log_row::temperature_log::dsl as temperature_log_dsl, StorageConnection, +}; + +use crate::repository_error::RepositoryError; + +use chrono::NaiveDateTime; +use diesel::prelude::*; + +table! { + temperature_log (id) { + id -> Text, + temperature -> Float, + sensor_id -> Text, + location_id -> Nullable, + store_id -> Nullable, + timestamp -> Timestamp, + } +} + +table! { + #[sql_name = "temperature_log"] + temperature_log_is_sync_update (id) { + id -> Text, + is_sync_update -> Bool, + } +} + +joinable!(temperature_log -> sensor (sensor_id)); +joinable!(temperature_log -> store (store_id)); +joinable!(temperature_log -> location (location_id)); + +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_log"] +pub struct TemperatureLogRow { + pub id: String, + pub temperature: f32, + pub sensor_id: String, + pub location_id: Option, + pub store_id: Option, + pub timestamp: NaiveDateTime, +} + +impl Default for TemperatureLogRow { + fn default() -> Self { + TemperatureLogRow { + id: Default::default(), + temperature: Default::default(), + sensor_id: Default::default(), + location_id: None, + store_id: None, + timestamp: Default::default(), + } + } +} +pub struct TemperatureLogRowRepository<'a> { + connection: &'a StorageConnection, +} + +impl<'a> TemperatureLogRowRepository<'a> { + pub fn new(connection: &'a StorageConnection) -> Self { + TemperatureLogRowRepository { connection } + } + + #[cfg(feature = "postgres")] + pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + diesel::insert_into(temperature_log_dsl::temperature_log) + .values(row) + .on_conflict(temperature_log_dsl::id) + .do_update() + .set(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + #[cfg(not(feature = "postgres"))] + pub fn _upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + diesel::replace_into(temperature_log_dsl::temperature_log) + .values(row) + .execute(&self.connection.connection)?; + Ok(()) + } + + pub fn upsert_one(&self, row: &TemperatureLogRow) -> Result<(), RepositoryError> { + self._upsert_one(row)?; + Ok(()) + } + + pub fn find_one_by_id(&self, id: &str) -> Result, RepositoryError> { + let result = temperature_log_dsl::temperature_log + .filter(temperature_log_dsl::id.eq(id)) + .first(&self.connection.connection) + .optional()?; + Ok(result) + } + + pub fn find_many_by_id( + &self, + ids: &[String], + ) -> Result, RepositoryError> { + Ok(temperature_log_dsl::temperature_log + .filter(temperature_log_dsl::id.eq_any(ids)) + .load(&self.connection.connection)?) + } +} From 7a96d11cf8723349eb162b86339f67ac95f02f5b Mon Sep 17 00:00:00 2001 From: adrianwb Date: Thu, 24 Aug 2023 16:18:58 +0100 Subject: [PATCH 07/10] Missed out another couple of diesel-related changes --- server/repository/src/db_diesel/changelog/changelog.rs | 3 +++ server/repository/src/db_diesel/user_permission_row.rs | 4 ++++ 2 files changed, 7 insertions(+) diff --git a/server/repository/src/db_diesel/changelog/changelog.rs b/server/repository/src/db_diesel/changelog/changelog.rs index ef003497f2..3915151235 100644 --- a/server/repository/src/db_diesel/changelog/changelog.rs +++ b/server/repository/src/db_diesel/changelog/changelog.rs @@ -60,6 +60,9 @@ pub enum ChangelogTableName { NameStoreJoin, Document, Sensor, + TemperatureBreach, + TemperatureBreachConfig, + TemperatureLog, } #[derive(Clone, Queryable, Debug, PartialEq, Insertable)] diff --git a/server/repository/src/db_diesel/user_permission_row.rs b/server/repository/src/db_diesel/user_permission_row.rs index d9ae7f3e23..99fa8ea1d1 100644 --- a/server/repository/src/db_diesel/user_permission_row.rs +++ b/server/repository/src/db_diesel/user_permission_row.rs @@ -32,6 +32,10 @@ pub enum Permission { // sensor, SensorMutate, SensorQuery, + // no existing mSupply permissions for temperature log/breach (which shouldn't be user editable) + // but one for temperature_breach_config, + TemperatureBreachConfigMutate, + TemperatureBreachConfigQuery, // stock line StockLineQuery, StockLineMutate, From 663b3f914faf22647c4829d4c9877fd348a40636 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Fri, 25 Aug 2023 14:17:25 +0100 Subject: [PATCH 08/10] Changed floats to doubles --- .../src/db_diesel/temperature_breach_config_row.rs | 8 ++++---- server/repository/src/db_diesel/temperature_breach_row.rs | 8 ++++---- server/repository/src/db_diesel/temperature_log_row.rs | 4 ++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/server/repository/src/db_diesel/temperature_breach_config_row.rs b/server/repository/src/db_diesel/temperature_breach_config_row.rs index 8c99feea5c..67875306c9 100644 --- a/server/repository/src/db_diesel/temperature_breach_config_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_config_row.rs @@ -15,8 +15,8 @@ table! { description -> Text, is_active -> Bool, store_id -> Nullable, - minimum_temperature -> Float, - maximum_temperature -> Float, + minimum_temperature -> Double, + maximum_temperature -> Double, } } @@ -41,8 +41,8 @@ pub struct TemperatureBreachConfigRow { pub description: String, pub is_active: bool, pub store_id: Option, - pub minimum_temperature: f32, - pub maximum_temperature: f32, + pub minimum_temperature: f64, + pub maximum_temperature: f64, } impl Default for TemperatureBreachConfigRow { diff --git a/server/repository/src/db_diesel/temperature_breach_row.rs b/server/repository/src/db_diesel/temperature_breach_row.rs index 99f3f1e485..c6c2b94b62 100644 --- a/server/repository/src/db_diesel/temperature_breach_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_row.rs @@ -21,8 +21,8 @@ table! { start_timestamp -> Timestamp, end_timestamp -> Timestamp, acknowledged -> Bool, - threshold_minimum -> Float, - threshold_maximum -> Float, + threshold_minimum -> Double, + threshold_maximum -> Double, threshold_duration -> Integer, } } @@ -63,8 +63,8 @@ pub struct TemperatureBreachRow { pub start_timestamp: NaiveDateTime, pub end_timestamp: NaiveDateTime, pub acknowledged: bool, - pub threshold_minimum: f32, - pub threshold_maximum: f32, + pub threshold_minimum: f64, + pub threshold_maximum: f64, pub threshold_duration: i32, } diff --git a/server/repository/src/db_diesel/temperature_log_row.rs b/server/repository/src/db_diesel/temperature_log_row.rs index 5605323001..f3c411040e 100644 --- a/server/repository/src/db_diesel/temperature_log_row.rs +++ b/server/repository/src/db_diesel/temperature_log_row.rs @@ -11,7 +11,7 @@ use diesel::prelude::*; table! { temperature_log (id) { id -> Text, - temperature -> Float, + temperature -> Double, sensor_id -> Text, location_id -> Nullable, store_id -> Nullable, @@ -36,7 +36,7 @@ joinable!(temperature_log -> location (location_id)); #[table_name = "temperature_log"] pub struct TemperatureLogRow { pub id: String, - pub temperature: f32, + pub temperature: f64, pub sensor_id: String, pub location_id: Option, pub store_id: Option, From 421144c499c79b8b77bd81ce2d1830781fcd1788 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Fri, 25 Aug 2023 14:18:33 +0100 Subject: [PATCH 09/10] Too soon - commented out for now --- server/repository/src/db_diesel/user_permission_row.rs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/server/repository/src/db_diesel/user_permission_row.rs b/server/repository/src/db_diesel/user_permission_row.rs index 99fa8ea1d1..c55dd2ba11 100644 --- a/server/repository/src/db_diesel/user_permission_row.rs +++ b/server/repository/src/db_diesel/user_permission_row.rs @@ -34,8 +34,8 @@ pub enum Permission { SensorQuery, // no existing mSupply permissions for temperature log/breach (which shouldn't be user editable) // but one for temperature_breach_config, - TemperatureBreachConfigMutate, - TemperatureBreachConfigQuery, + //TemperatureBreachConfigMutate, + //TemperatureBreachConfigQuery, // stock line StockLineQuery, StockLineMutate, From 8bc9323c5d6c4a06851d3b1bd84a47fb69bbe489 Mon Sep 17 00:00:00 2001 From: adrianwb Date: Mon, 28 Aug 2023 12:06:29 +0100 Subject: [PATCH 10/10] Modify defaults --- .../temperature_breach_config_row.rs | 16 +------------ .../src/db_diesel/temperature_breach_row.rs | 23 +++---------------- .../src/db_diesel/temperature_log_row.rs | 14 +---------- 3 files changed, 5 insertions(+), 48 deletions(-) diff --git a/server/repository/src/db_diesel/temperature_breach_config_row.rs b/server/repository/src/db_diesel/temperature_breach_config_row.rs index 67875306c9..5eca63a143 100644 --- a/server/repository/src/db_diesel/temperature_breach_config_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_config_row.rs @@ -30,7 +30,7 @@ table! { joinable!(temperature_breach_config -> store (store_id)); -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq, Default)] #[changeset_options(treat_none_as_null = "true")] #[table_name = "temperature_breach_config"] pub struct TemperatureBreachConfigRow { @@ -45,20 +45,6 @@ pub struct TemperatureBreachConfigRow { pub maximum_temperature: f64, } -impl Default for TemperatureBreachConfigRow { - fn default() -> Self { - TemperatureBreachConfigRow { - id: Default::default(), - duration: Default::default(), - r#type: TemperatureBreachRowType::HotConsecutive, - description: Default::default(), - is_active: false, - store_id: None, - minimum_temperature: Default::default(), - maximum_temperature: Default::default(), - } - } -} pub struct TemperatureBreachConfigRowRepository<'a> { connection: &'a StorageConnection, } diff --git a/server/repository/src/db_diesel/temperature_breach_row.rs b/server/repository/src/db_diesel/temperature_breach_row.rs index c6c2b94b62..0693e37283 100644 --- a/server/repository/src/db_diesel/temperature_breach_row.rs +++ b/server/repository/src/db_diesel/temperature_breach_row.rs @@ -39,17 +39,18 @@ joinable!(temperature_breach -> sensor (sensor_id)); joinable!(temperature_breach -> store (store_id)); joinable!(temperature_breach -> location (location_id)); -#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)] #[serde(rename_all = "SCREAMING_SNAKE_CASE")] #[DbValueStyle = "SCREAMING_SNAKE_CASE"] pub enum TemperatureBreachRowType { ColdConsecutive, ColdCumulative, + #[default] HotConsecutive, HotCumulative, } -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq, Default)] #[changeset_options(treat_none_as_null = "true")] #[table_name = "temperature_breach"] pub struct TemperatureBreachRow { @@ -68,24 +69,6 @@ pub struct TemperatureBreachRow { pub threshold_duration: i32, } -impl Default for TemperatureBreachRow { - fn default() -> Self { - TemperatureBreachRow { - id: Default::default(), - duration: Default::default(), - r#type: TemperatureBreachRowType::HotConsecutive, - sensor_id: Default::default(), - location_id: None, - store_id: None, - start_timestamp: Default::default(), - end_timestamp: Default::default(), - acknowledged: false, - threshold_minimum: Default::default(), - threshold_maximum: Default::default(), - threshold_duration: Default::default(), - } - } -} pub struct TemperatureBreachRowRepository<'a> { connection: &'a StorageConnection, } diff --git a/server/repository/src/db_diesel/temperature_log_row.rs b/server/repository/src/db_diesel/temperature_log_row.rs index f3c411040e..11f1f1088f 100644 --- a/server/repository/src/db_diesel/temperature_log_row.rs +++ b/server/repository/src/db_diesel/temperature_log_row.rs @@ -31,7 +31,7 @@ joinable!(temperature_log -> sensor (sensor_id)); joinable!(temperature_log -> store (store_id)); joinable!(temperature_log -> location (location_id)); -#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq)] +#[derive(Clone, Queryable, Insertable, AsChangeset, Debug, PartialEq, Default)] #[changeset_options(treat_none_as_null = "true")] #[table_name = "temperature_log"] pub struct TemperatureLogRow { @@ -43,18 +43,6 @@ pub struct TemperatureLogRow { pub timestamp: NaiveDateTime, } -impl Default for TemperatureLogRow { - fn default() -> Self { - TemperatureLogRow { - id: Default::default(), - temperature: Default::default(), - sensor_id: Default::default(), - location_id: None, - store_id: None, - timestamp: Default::default(), - } - } -} pub struct TemperatureLogRowRepository<'a> { connection: &'a StorageConnection, }