Skip to content

Commit

Permalink
Merge pull request #5295 from msupply-foundation/5212-indicator_row-a…
Browse files Browse the repository at this point in the history
…nd-column-tables

5212 indicator row and column tables
  • Loading branch information
Chris-Petty authored Nov 4, 2024
2 parents 5be669f + 265c397 commit 9e58843
Show file tree
Hide file tree
Showing 15 changed files with 863 additions and 2 deletions.
93 changes: 93 additions & 0 deletions server/repository/src/db_diesel/indicator_column.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
use super::{
indicator_column_row::{indicator_column, IndicatorColumnRow},
DBType, StorageConnection,
};

use crate::{diesel_macros::apply_equal_filter, repository_error::RepositoryError};

use crate::{EqualFilter, Pagination};

use diesel::prelude::*;

pub struct IndicatorColumnRepository<'a> {
connection: &'a StorageConnection,
}

#[derive(Clone, Debug, PartialEq, Default)]
pub struct IndicatorColumnFilter {
pub id: Option<EqualFilter<String>>,
pub program_indicator_id: Option<EqualFilter<String>>,
}

impl<'a> IndicatorColumnRepository<'a> {
pub fn new(connection: &'a StorageConnection) -> Self {
IndicatorColumnRepository { connection }
}

pub fn count(&self, filter: Option<IndicatorColumnFilter>) -> Result<i64, RepositoryError> {
let query = Self::create_filtered_query(filter);

Ok(query
.count()
.get_result(self.connection.lock().connection())?)
}

pub fn query_by_filter(
&self,
filter: IndicatorColumnFilter,
) -> Result<Vec<IndicatorColumnRow>, RepositoryError> {
self.query(Pagination::new(), Some(filter))
}

pub fn create_filtered_query(filter: Option<IndicatorColumnFilter>) -> BoxedIndicatorQuery {
let mut query = indicator_column::table.into_boxed();
// Filter out inactive program_indicators by default
query = query.filter(indicator_column::is_active.eq(true));

if let Some(f) = filter {
apply_equal_filter!(query, f.id, indicator_column::id);
apply_equal_filter!(
query,
f.program_indicator_id,
indicator_column::program_indicator_id
);
}

query
}

pub fn query(
&self,
pagination: Pagination,
filter: Option<IndicatorColumnFilter>,
) -> Result<Vec<IndicatorColumnRow>, RepositoryError> {
let query = Self::create_filtered_query(filter);

// Debug diesel query
// println!("{}", diesel::debug_query::<DBType, _>(&query).to_string());

let result = query
.offset(pagination.offset as i64)
.limit(pagination.limit as i64)
.load::<IndicatorColumnRow>(self.connection.lock().connection())?;

Ok(result)
}
}
type BoxedIndicatorQuery = indicator_column::BoxedQuery<'static, DBType>;

impl IndicatorColumnFilter {
pub fn new() -> IndicatorColumnFilter {
Self::default()
}

pub fn id(mut self, filter: EqualFilter<String>) -> Self {
self.id = Some(filter);
self
}

pub fn program_indicator_id(mut self, filter: EqualFilter<String>) -> Self {
self.program_indicator_id = Some(filter);
self
}
}
80 changes: 80 additions & 0 deletions server/repository/src/db_diesel/indicator_column_row.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
use super::{IndicatorValueType, StorageConnection};

use crate::{repository_error::RepositoryError, Upsert};

use diesel::prelude::*;

table! {
indicator_column (id) {
id -> Text,
program_indicator_id -> Text,
column_number -> Integer,
header ->Text,
value_type -> Nullable<crate::IndicatorValueTypeMapping>,
default_value -> Text,
is_active -> Bool,
}
}

#[derive(Clone, Insertable, Queryable, Debug, PartialEq, AsChangeset, Default)]
#[diesel(table_name = indicator_column)]
pub struct IndicatorColumnRow {
pub id: String,
pub program_indicator_id: String,
pub column_number: i32,
pub header: String,
pub value_type: Option<IndicatorValueType>,
pub default_value: String,
pub is_active: bool,
}

pub struct IndicatorColumnRowRepository<'a> {
connection: &'a StorageConnection,
}

impl<'a> IndicatorColumnRowRepository<'a> {
pub fn new(connection: &'a StorageConnection) -> Self {
IndicatorColumnRowRepository { connection }
}

pub fn upsert_one(&self, row: &IndicatorColumnRow) -> Result<(), RepositoryError> {
let query = diesel::insert_into(indicator_column::table)
.values(row)
.on_conflict(indicator_column::id)
.do_update()
.set(row);

// Debug diesel query
// println!("{}", diesel::debug_query::<DBType, _>(&query).to_string());

query.execute(self.connection.lock().connection())?;

Ok(())
}

pub fn find_one_by_id(
&self,
record_id: &str,
) -> Result<Option<IndicatorColumnRow>, RepositoryError> {
let result = indicator_column::table
.filter(indicator_column::id.eq(record_id))
.first(self.connection.lock().connection())
.optional()?;
Ok(result)
}
}

impl Upsert for IndicatorColumnRow {
fn upsert(&self, con: &StorageConnection) -> Result<Option<i64>, RepositoryError> {
IndicatorColumnRowRepository::new(con).upsert_one(self)?;
Ok(None) // Table not in Changelog
}

// Test only
fn assert_upserted(&self, con: &StorageConnection) {
assert_eq!(
IndicatorColumnRowRepository::new(con).find_one_by_id(&self.id),
Ok(Some(self.clone()))
)
}
}
103 changes: 103 additions & 0 deletions server/repository/src/db_diesel/indicator_line.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use super::{
indicator_line_row::{indicator_line, IndicatorLineRow},
DBType, StorageConnection,
};

use crate::{
diesel_macros::{apply_equal_filter, apply_string_filter},
repository_error::RepositoryError,
};

use crate::{EqualFilter, Pagination, StringFilter};

use diesel::prelude::*;

pub struct IndicatorLineRepository<'a> {
connection: &'a StorageConnection,
}

#[derive(Clone, Debug, PartialEq, Default)]
pub struct IndicatorLineFilter {
pub id: Option<EqualFilter<String>>,
pub program_indicator_id: Option<EqualFilter<String>>,
pub code: Option<StringFilter>,
}

impl<'a> IndicatorLineRepository<'a> {
pub fn new(connection: &'a StorageConnection) -> Self {
IndicatorLineRepository { connection }
}

pub fn count(&self, filter: Option<IndicatorLineFilter>) -> Result<i64, RepositoryError> {
let query = Self::create_filtered_query(filter);

Ok(query
.count()
.get_result(self.connection.lock().connection())?)
}

pub fn query_by_filter(
&self,
filter: IndicatorLineFilter,
) -> Result<Vec<IndicatorLineRow>, RepositoryError> {
self.query(Pagination::new(), Some(filter))
}

pub fn create_filtered_query(filter: Option<IndicatorLineFilter>) -> BoxedIndicatorQuery {
let mut query = indicator_line::table.into_boxed();
// Filter out inactive program_indicators by default
query = query.filter(indicator_line::is_active.eq(true));

if let Some(f) = filter {
apply_equal_filter!(query, f.id, indicator_line::id);
apply_equal_filter!(
query,
f.program_indicator_id,
indicator_line::program_indicator_id
);
apply_string_filter!(query, f.code, indicator_line::code);
}

query
}

pub fn query(
&self,
pagination: Pagination,
filter: Option<IndicatorLineFilter>,
) -> Result<Vec<IndicatorLineRow>, RepositoryError> {
let query = Self::create_filtered_query(filter);

// Debug diesel query
// println!("{}", diesel::debug_query::<DBType, _>(&query).to_string());

let result = query
.offset(pagination.offset as i64)
.limit(pagination.limit as i64)
.load::<IndicatorLineRow>(self.connection.lock().connection())?;

Ok(result)
}
}
type BoxedIndicatorQuery = indicator_line::BoxedQuery<'static, DBType>;

impl IndicatorLineFilter {
pub fn new() -> IndicatorLineFilter {
Self::default()
}

pub fn id(mut self, filter: EqualFilter<String>) -> Self {
self.id = Some(filter);
self
}

pub fn program_indicator_id(mut self, filter: EqualFilter<String>) -> Self {
self.program_indicator_id = Some(filter);
self
}

pub fn code(mut self, filter: StringFilter) -> Self {
self.code = Some(filter);
self
}
}
92 changes: 92 additions & 0 deletions server/repository/src/db_diesel/indicator_line_row.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,92 @@
use super::StorageConnection;

use crate::{repository_error::RepositoryError, Upsert};

use diesel::prelude::*;
use diesel_derive_enum::DbEnum;
use serde::{Deserialize, Serialize};

#[derive(DbEnum, Debug, Clone, PartialEq, Eq, Serialize, Deserialize, Default)]
#[serde(rename_all = "SCREAMING_SNAKE_CASE")]
#[DbValueStyle = "SCREAMING_SNAKE_CASE"]
pub enum IndicatorValueType {
#[serde(rename = "string")]
String,
#[serde(rename = "number")]
#[default]
Number,
}

table! {
indicator_line (id) {
id -> Text,
program_indicator_id -> Text,
line_number -> Integer,
description->Text,
code -> Text,
value_type -> Nullable<crate::IndicatorValueTypeMapping>,
default_value -> Text,
is_required -> Bool,
is_active -> Bool,
}
}

#[derive(Clone, Insertable, Queryable, Debug, PartialEq, AsChangeset, Default)]
#[diesel(table_name = indicator_line)]
pub struct IndicatorLineRow {
pub id: String,
pub program_indicator_id: String,
pub line_number: i32,
pub description: String,
pub code: String,
pub value_type: Option<IndicatorValueType>,
pub default_value: String,
pub is_required: bool,
pub is_active: bool,
}

pub struct IndicatorLineRowRepository<'a> {
connection: &'a StorageConnection,
}

impl<'a> IndicatorLineRowRepository<'a> {
pub fn new(connection: &'a StorageConnection) -> Self {
IndicatorLineRowRepository { connection }
}

pub fn upsert_one(&self, row: &IndicatorLineRow) -> Result<(), RepositoryError> {
diesel::insert_into(indicator_line::table)
.values(row)
.on_conflict(indicator_line::id)
.do_update()
.set(row)
.execute(self.connection.lock().connection())?;
Ok(())
}

pub fn find_one_by_id(
&self,
record_id: &str,
) -> Result<Option<IndicatorLineRow>, RepositoryError> {
let result = indicator_line::table
.filter(indicator_line::id.eq(record_id))
.first(self.connection.lock().connection())
.optional()?;
Ok(result)
}
}

impl Upsert for IndicatorLineRow {
fn upsert(&self, con: &StorageConnection) -> Result<Option<i64>, RepositoryError> {
IndicatorLineRowRepository::new(con).upsert_one(self)?;
Ok(None) // Table not in Changelog
}

// Test only
fn assert_upserted(&self, con: &StorageConnection) {
assert_eq!(
IndicatorLineRowRepository::new(con).find_one_by_id(&self.id),
Ok(Some(self.clone()))
)
}
}
6 changes: 6 additions & 0 deletions server/repository/src/db_diesel/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ mod filter_restriction;
mod filter_sort_pagination;
pub mod form_schema;
mod form_schema_row;
pub mod indicator_column;
mod indicator_column_row;
pub mod indicator_line;
mod indicator_line_row;
pub mod inventory_adjustment_reason;
mod inventory_adjustment_reason_row;
pub mod invoice;
Expand Down Expand Up @@ -160,6 +164,8 @@ pub use encounter_row::*;
pub use filter_sort_pagination::*;
pub use form_schema::*;
pub use form_schema_row::*;
pub use indicator_column_row::*;
pub use indicator_line_row::*;
pub use inventory_adjustment_reason_row::*;
pub use invoice::*;
pub use invoice_line::*;
Expand Down
1 change: 0 additions & 1 deletion server/repository/src/db_diesel/program_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@ impl<'a> ProgramIndicatorRepository<'a> {
}

pub fn count(&self, filter: Option<ProgramIndicatorFilter>) -> Result<i64, RepositoryError> {
// TODO (beyond M1), check that store_id matches current store
let query = Self::create_filtered_query(filter);

Ok(query
Expand Down
Loading

0 comments on commit 9e58843

Please sign in to comment.