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/diesel_schema.rs b/server/repository/src/db_diesel/diesel_schema.rs index 13c00c2af5..39eeeec101 100644 --- a/server/repository/src/db_diesel/diesel_schema.rs +++ b/server/repository/src/db_diesel/diesel_schema.rs @@ -10,13 +10,18 @@ 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_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!( unit, location, 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 1a289e6cd2..c682bd43a4 100644 --- a/server/repository/src/db_diesel/mod.rs +++ b/server/repository/src/db_diesel/mod.rs @@ -73,6 +73,12 @@ mod store_row; 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; mod unit_row; mod user; mod user_permission; @@ -146,6 +152,12 @@ 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_config::*; +pub use temperature_breach_config_row::*; +pub use temperature_breach_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_breach.rs b/server/repository/src/db_diesel/temperature_breach.rs new file mode 100644 index 0000000000..656ef021be --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach.rs @@ -0,0 +1,180 @@ +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 new file mode 100644 index 0000000000..88c0f933e4 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_config.rs @@ -0,0 +1,150 @@ +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 new file mode 100644 index 0000000000..5eca63a143 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_config_row.rs @@ -0,0 +1,100 @@ +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 -> Double, + maximum_temperature -> Double, + } +} + +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, Default)] +#[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: f64, + pub maximum_temperature: f64, +} + +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 new file mode 100644 index 0000000000..0693e37283 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_breach_row.rs @@ -0,0 +1,124 @@ +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 -> Double, + threshold_maximum -> Double, + 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, 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, Default)] +#[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: f64, + pub threshold_maximum: f64, + pub threshold_duration: i32, +} + +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 new file mode 100644 index 0000000000..50c02559a1 --- /dev/null +++ b/server/repository/src/db_diesel/temperature_log.rs @@ -0,0 +1,139 @@ +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 new file mode 100644 index 0000000000..11f1f1088f --- /dev/null +++ b/server/repository/src/db_diesel/temperature_log_row.rs @@ -0,0 +1,95 @@ +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 -> Double, + 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, Default)] +#[changeset_options(treat_none_as_null = "true")] +#[table_name = "temperature_log"] +pub struct TemperatureLogRow { + pub id: String, + pub temperature: f64, + pub sensor_id: String, + pub location_id: Option, + pub store_id: Option, + pub timestamp: NaiveDateTime, +} + +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)?) + } +} diff --git a/server/repository/src/db_diesel/user_permission_row.rs b/server/repository/src/db_diesel/user_permission_row.rs index d9ae7f3e23..c55dd2ba11 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,