Skip to content

Commit d8d3475

Browse files
authored
Merge pull request #6885 from msupply-foundation/6838-add-prefs-repo-layer
6838 add prefs repo layer
2 parents a70460a + 5bccdaa commit d8d3475

File tree

4 files changed

+225
-2
lines changed

4 files changed

+225
-2
lines changed

server/repository/src/db_diesel/changelog/changelog.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -121,11 +121,12 @@ pub enum ChangelogTableName {
121121
Report,
122122
FormSchema,
123123
PluginData,
124+
Preference,
124125
}
125126

126127
pub(crate) enum ChangeLogSyncStyle {
127-
Legacy,
128-
Central,
128+
Legacy, // Everything that goes to Legacy mSupply server
129+
Central, // Data created on Open-mSupply central server
129130
Remote,
130131
File,
131132
RemoteAndCentral, // These records will sync like remote record if store_id exist, otherwise they will sync like central records
@@ -197,6 +198,7 @@ impl ChangelogTableName {
197198
ChangelogTableName::Report => ChangeLogSyncStyle::Central,
198199
ChangelogTableName::FormSchema => ChangeLogSyncStyle::Central,
199200
ChangelogTableName::PluginData => ChangeLogSyncStyle::RemoteAndCentral,
201+
ChangelogTableName::Preference => ChangeLogSyncStyle::Central,
200202
}
201203
}
202204
}

server/repository/src/db_diesel/mod.rs

+4
Original file line numberDiff line numberDiff line change
@@ -94,6 +94,8 @@ mod patient;
9494
pub mod period;
9595
pub mod plugin_data;
9696
mod plugin_data_row;
97+
pub mod preference;
98+
mod preference_row;
9799
pub mod printer;
98100
pub mod printer_row;
99101
pub mod program_enrolment;
@@ -225,6 +227,8 @@ pub use patient::*;
225227
pub use period::*;
226228
pub use plugin_data::*;
227229
pub use plugin_data_row::*;
230+
pub use preference::*;
231+
pub use preference_row::*;
228232
pub use printer_row::*;
229233
pub use program_enrolment::*;
230234
pub use program_enrolment_row::*;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
use diesel::{
2+
dsl::{InnerJoin, IntoBoxed},
3+
prelude::*,
4+
};
5+
6+
use crate::diesel_macros::apply_equal_filter;
7+
8+
use super::{
9+
preference_row::{preference, PreferenceRow},
10+
store_row::store,
11+
DBType, EqualFilter, Pagination, RepositoryError, StorageConnection, StoreRow,
12+
};
13+
14+
#[derive(PartialEq, Debug, Clone, Default)]
15+
pub struct Preference {
16+
pub preference_row: PreferenceRow,
17+
}
18+
19+
#[derive(Clone, Default)]
20+
pub struct PreferenceFilter {
21+
pub id: Option<EqualFilter<String>>,
22+
}
23+
24+
impl PreferenceFilter {
25+
pub fn new() -> PreferenceFilter {
26+
PreferenceFilter::default()
27+
}
28+
29+
pub fn id(mut self, filter: EqualFilter<String>) -> Self {
30+
self.id = Some(filter);
31+
self
32+
}
33+
}
34+
35+
pub type PreferenceJoin = (PreferenceRow, StoreRow);
36+
37+
pub struct PreferenceRepository<'a> {
38+
connection: &'a StorageConnection,
39+
}
40+
41+
impl<'a> PreferenceRepository<'a> {
42+
pub fn new(connection: &'a StorageConnection) -> Self {
43+
PreferenceRepository { connection }
44+
}
45+
46+
pub fn query_one(
47+
&self,
48+
filter: PreferenceFilter,
49+
) -> Result<Option<Preference>, RepositoryError> {
50+
Ok(self.query_by_filter(filter)?.pop())
51+
}
52+
53+
pub fn query_by_filter(
54+
&self,
55+
filter: PreferenceFilter,
56+
) -> Result<Vec<Preference>, RepositoryError> {
57+
self.query(Pagination::new(), Some(filter))
58+
}
59+
60+
pub fn query(
61+
&self,
62+
pagination: Pagination,
63+
filter: Option<PreferenceFilter>,
64+
) -> Result<Vec<Preference>, RepositoryError> {
65+
let query = create_filtered_query(filter);
66+
67+
let final_query = query
68+
.offset(pagination.offset as i64)
69+
.limit(pagination.limit as i64);
70+
71+
// Debug diesel query
72+
//println!(
73+
// "{}",
74+
// diesel::debug_query::<DBType, _>(&final_query).to_string()
75+
//);
76+
let result = final_query
77+
.load::<PreferenceJoin>(self.connection.lock().connection())?
78+
.into_iter()
79+
.map(|(preference_row, _store_row)| Preference { preference_row })
80+
.collect();
81+
82+
Ok(result)
83+
}
84+
}
85+
86+
type BoxedPreferenceQuery = IntoBoxed<'static, InnerJoin<preference::table, store::table>, DBType>;
87+
88+
fn create_filtered_query(filter: Option<PreferenceFilter>) -> BoxedPreferenceQuery {
89+
let mut query = preference::table.inner_join(store::table).into_boxed();
90+
91+
if let Some(f) = filter {
92+
let PreferenceFilter { id } = f;
93+
94+
apply_equal_filter!(query, id, preference::id);
95+
}
96+
query
97+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
use crate::{
2+
ChangeLogInsertRow, ChangelogRepository, ChangelogTableName, RepositoryError, RowActionType,
3+
StorageConnection, Upsert,
4+
};
5+
6+
use super::{preference_row::preference::dsl::*, store_row::store};
7+
use serde::{Deserialize, Serialize};
8+
9+
use diesel::prelude::*;
10+
11+
table! {
12+
preference (id) {
13+
id -> Text,
14+
key -> Text,
15+
value -> Text,
16+
store_id -> Nullable<Text>,
17+
}
18+
}
19+
20+
joinable!(preference -> store (store_id));
21+
22+
allow_tables_to_appear_in_same_query!(preference, store);
23+
24+
#[derive(
25+
Clone, Insertable, Queryable, Debug, PartialEq, AsChangeset, Eq, Serialize, Deserialize, Default,
26+
)]
27+
#[diesel(table_name = preference)]
28+
pub struct PreferenceRow {
29+
pub id: String,
30+
pub key: String,
31+
pub value: String,
32+
pub store_id: Option<String>,
33+
}
34+
35+
pub struct PreferenceRowRepository<'a> {
36+
connection: &'a StorageConnection,
37+
}
38+
39+
impl<'a> PreferenceRowRepository<'a> {
40+
pub fn new(connection: &'a StorageConnection) -> Self {
41+
PreferenceRowRepository { connection }
42+
}
43+
44+
fn upsert_one(&self, preference_row: &PreferenceRow) -> Result<i64, RepositoryError> {
45+
diesel::insert_into(preference::table)
46+
.values(preference_row)
47+
.on_conflict(id)
48+
.do_update()
49+
.set(preference_row)
50+
.execute(self.connection.lock().connection())?;
51+
52+
self.insert_changelog(preference_row.to_owned(), RowActionType::Upsert)
53+
}
54+
55+
fn insert_changelog(
56+
&self,
57+
row: PreferenceRow,
58+
action: RowActionType,
59+
) -> Result<i64, RepositoryError> {
60+
let row = ChangeLogInsertRow {
61+
table_name: ChangelogTableName::Preference,
62+
record_id: row.id,
63+
row_action: action,
64+
store_id: row.store_id.clone(),
65+
name_link_id: None,
66+
};
67+
ChangelogRepository::new(self.connection).insert(&row)
68+
}
69+
70+
pub fn find_one_by_key(
71+
&self,
72+
preference_key: &str,
73+
) -> Result<Option<PreferenceRow>, RepositoryError> {
74+
let result = preference
75+
.filter(key.eq(preference_key))
76+
.first(self.connection.lock().connection())
77+
.optional()?;
78+
Ok(result)
79+
}
80+
81+
pub fn find_one_by_id(
82+
&self,
83+
preference_id: &str,
84+
) -> Result<Option<PreferenceRow>, RepositoryError> {
85+
let result = preference::table
86+
.filter(preference::id.eq(preference_id))
87+
.first(self.connection.lock().connection())
88+
.optional()?;
89+
Ok(result)
90+
}
91+
92+
pub fn delete(&self, preference_id: &str) -> Result<Option<i64>, RepositoryError> {
93+
let old_row = self.find_one_by_id(preference_id)?;
94+
let change_log_id = match old_row {
95+
Some(old_row) => self.insert_changelog(old_row, RowActionType::Delete)?,
96+
None => {
97+
return Ok(None);
98+
}
99+
};
100+
101+
diesel::delete(preference.filter(preference::id.eq(preference_id)))
102+
.execute(self.connection.lock().connection())?;
103+
Ok(Some(change_log_id))
104+
}
105+
}
106+
107+
impl Upsert for PreferenceRow {
108+
fn upsert(&self, con: &StorageConnection) -> Result<Option<i64>, RepositoryError> {
109+
let cursor_id = PreferenceRowRepository::new(con).upsert_one(self)?;
110+
Ok(Some(cursor_id))
111+
}
112+
113+
// Test only
114+
fn assert_upserted(&self, con: &StorageConnection) {
115+
assert_eq!(
116+
PreferenceRowRepository::new(con).find_one_by_key(&self.key),
117+
Ok(Some(self.clone()))
118+
)
119+
}
120+
}

0 commit comments

Comments
 (0)