Skip to content

Commit

Permalink
Merge pull request #288 from msupply-foundation/285-generate-paramete…
Browse files Browse the repository at this point in the history
…rs-from-sql

285 generate parameters from sql
  • Loading branch information
EthanMcQ-TMF authored Feb 15, 2024
2 parents 1cd7fc4 + 96443c3 commit 0ee9514
Show file tree
Hide file tree
Showing 20 changed files with 205 additions and 51 deletions.
3 changes: 3 additions & 0 deletions backend/graphql/notification_config/src/mutations/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ pub struct UpdateNotificationConfigInput {
pub title: Option<String>,
pub configuration_data: Option<String>,
pub parameters: Option<String>,
pub parameter_query_id: Option<String>,
pub status: Option<ConfigStatus>,
pub recipient_ids: Option<Vec<String>>,
pub recipient_list_ids: Option<Vec<String>>,
Expand Down Expand Up @@ -54,6 +55,7 @@ impl From<UpdateNotificationConfigInput> for UpdateNotificationConfig {
configuration_data,
status,
parameters,
parameter_query_id,
recipient_ids,
recipient_list_ids,
sql_recipient_list_ids,
Expand All @@ -66,6 +68,7 @@ impl From<UpdateNotificationConfigInput> for UpdateNotificationConfig {
configuration_data,
status: status.map(ConfigStatus::to_domain),
parameters,
parameter_query_id,
recipient_ids,
recipient_list_ids,
sql_recipient_list_ids,
Expand Down
4 changes: 4 additions & 0 deletions backend/graphql/types/src/types/notification_config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,10 @@ impl NotificationConfigNode {
&self.row().parameters
}

pub async fn parameter_query_id(&self) -> &Option<String> {
&self.row().parameter_query_id
}

pub async fn recipient_ids(&self) -> &[String] {
&self.row().recipient_ids
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
-- This file should undo anything in `up.sql`
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ALTER TABLE notification_config ADD COLUMN parameter_query_id TEXT;
2 changes: 2 additions & 0 deletions backend/repository/src/db_diesel/notification_config_row.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ table! {
configuration_data -> Text,
status -> crate::db_diesel::notification_config_row::NotificationConfigStatusMapping,
parameters -> Text,
parameter_query_id -> Nullable<Text>,
recipient_ids -> Text,
recipient_list_ids -> Text,
sql_recipient_list_ids -> Text,
Expand Down Expand Up @@ -86,6 +87,7 @@ pub struct NotificationConfigRow {
pub configuration_data: String,
pub status: NotificationConfigStatus,
pub parameters: String, // JSON object {key: "value"}
pub parameter_query_id: Option<String>,
pub recipient_ids: String, // JSON array of strings (ids)
pub recipient_list_ids: String, // JSON array of strings (ids)
pub sql_recipient_list_ids: String, // JSON array of strings (ids)
Expand Down
17 changes: 5 additions & 12 deletions backend/scheduled/src/process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use chrono::{DateTime, NaiveDateTime, Utc};
use repository::{NotificationConfigKind, NotificationConfigRowRepository};
use service::{
notification::enqueue::{create_notification_events, NotificationContext, TemplateDefinition},
notification_config::{query::NotificationConfig, recipients::get_notification_targets},
notification_config::{query::NotificationConfig, recipients::get_notification_targets, parameters::get_notification_parameters},
service_provider::ServiceContext,
};

Expand Down Expand Up @@ -118,19 +118,12 @@ fn try_process_scheduled_notifications(
)));
}

let params = match scheduled_notification.parameters.len() {
0 => "[{}]".to_string(),
_ => scheduled_notification.parameters.clone(),
let param_results = get_notification_parameters(ctx, &scheduled_notification);
let mut all_params = match param_results {
Ok(val) => val,
Err(e) => return Err(NotificationError::InternalError(format!("Failed to fetch parameters: {:?}", e)))
};

let mut all_params: Vec<HashMap<String, serde_json::Value>> = serde_json::from_str(&params)
.map_err(|e| {
NotificationError::InternalError(format!(
"Failed to parse notification config parameters (expecting an array of params): {:?} - {}",
e, params
))
})?;

if all_params.len() == 0 {
// If no parameters are provided, create a single empty parameter set
all_params = vec![HashMap::new()];
Expand Down
1 change: 1 addition & 0 deletions backend/service/src/notification_config/create.rs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ pub fn generate(
configuration_data: "{}".to_string(),
status: NotificationConfigStatus::Disabled,
parameters: "{}".to_string(),
parameter_query_id: None,
recipient_ids: "[]".to_string(),
recipient_list_ids: "[]".to_string(),
sql_recipient_list_ids: "[]".to_string(),
Expand Down
1 change: 1 addition & 0 deletions backend/service/src/notification_config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub mod create;
pub mod delete;
pub mod duplicate;
pub mod intervals;
pub mod parameters;
pub mod query;
pub mod recipients;
pub mod update;
Expand Down
68 changes: 68 additions & 0 deletions backend/service/src/notification_config/parameters.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
use std::collections::HashMap;

use crate::service_provider::ServiceContext;
use crate::notification::NotificationServiceError;
use super::query::NotificationConfig;
use repository::NotificationQueryRowRepository;

pub fn get_notification_parameters(
ctx: &ServiceContext,
notification_config: &NotificationConfig,
) -> Result<Vec<HashMap<String, serde_json::Value>>, NotificationServiceError> {
// Fetch default parameters from config
let params_string = match notification_config.parameters.len() {
0 => "[]".to_string(),
_ => notification_config.parameters.clone(),
};
let sql_params_string = match &notification_config.parameter_query_id {
None => "[]".to_string(),
Some(query_id) => get_sql_parameters(ctx, query_id)?,
};

// Parse both sets of parameter strings, then merge the resulting vectors
let mut all_params: Vec<HashMap<String, serde_json::Value>> = serde_json::from_str(&params_string)
.map_err(|e| {
NotificationServiceError::InternalError(format!(
"Failed to parse notification config parameters (expecting an array of params_string): {:?} - {}",
e, params_string
))
})?;
let sql_params: Vec<HashMap<String, serde_json::Value>> = serde_json::from_str(&sql_params_string)
.map_err(|e| {
NotificationServiceError::InternalError(format!(
"Failed to parse notification sql parameters (expecting an array of params_string): {:?} - {}",
e, params_string
))
})?;
all_params.extend(sql_params);

return Ok(all_params);
}

fn get_sql_parameters(
ctx: &ServiceContext,
parameter_query_id: &String,
) -> Result<String, NotificationServiceError> {
// TODO: Maybe split these to a new database table
let repository = NotificationQueryRowRepository::new(&ctx.connection);
let query_record = repository.find_one_by_id(&parameter_query_id)?;

let sql_query = match query_record {
None => return Err(NotificationServiceError::InternalError(format!(
"No query found for parameter_query_id: {}", parameter_query_id)
)),
Some(record) => record.query,
};

let query_result = ctx
.service_provider
.datasource_service
.run_sql_query(sql_query)
.map_err(|e| {
NotificationServiceError::InternalError(format!("Error when fetching parameter_query_id: {} - {:?}",
parameter_query_id, e
))
})?;

return Ok(query_result.results);
}
3 changes: 3 additions & 0 deletions backend/service/src/notification_config/query.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub struct NotificationConfig {
pub configuration_data: String,
pub status: NotificationConfigStatus,
pub parameters: String,
pub parameter_query_id: Option<String>,
pub recipient_ids: Vec<String>,
pub recipient_list_ids: Vec<String>,
pub sql_recipient_list_ids: Vec<String>,
Expand All @@ -38,6 +39,7 @@ impl From<NotificationConfigRow> for NotificationConfig {
configuration_data,
status,
parameters,
parameter_query_id,
recipient_ids,
recipient_list_ids,
sql_recipient_list_ids,
Expand All @@ -52,6 +54,7 @@ impl From<NotificationConfigRow> for NotificationConfig {
configuration_data,
status,
parameters,
parameter_query_id,
recipient_ids: serde_json::from_str(&recipient_ids).unwrap_or_default(),
recipient_list_ids: serde_json::from_str(&recipient_list_ids).unwrap_or_default(),
sql_recipient_list_ids: serde_json::from_str(&sql_recipient_list_ids)
Expand Down
5 changes: 5 additions & 0 deletions backend/service/src/notification_config/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub struct UpdateNotificationConfig {
pub configuration_data: Option<String>,
pub status: Option<NotificationConfigStatus>,
pub parameters: Option<String>,
pub parameter_query_id: Option<String>,
pub recipient_ids: Option<Vec<String>>,
pub recipient_list_ids: Option<Vec<String>>,
pub sql_recipient_list_ids: Option<Vec<String>>,
Expand Down Expand Up @@ -71,6 +72,7 @@ pub fn generate(
configuration_data,
status,
parameters,
parameter_query_id,
recipient_ids,
recipient_list_ids,
sql_recipient_list_ids,
Expand Down Expand Up @@ -124,5 +126,8 @@ pub fn generate(
// Note: We usually reset the next check datetime in case the schedule has changed, or something needs to be recalculated
new_notification_config_row.next_due_datetime = next_due_datetime;

// We might want to clear out the parameter_query_id so it's allowed to be None
new_notification_config_row.parameter_query_id = parameter_query_id;

Ok(new_notification_config_row)
}
3 changes: 2 additions & 1 deletion frontend/packages/common/src/intl/locales/en/system.json
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@
"label.edit-user": "Edit User",
"label.edit-parameters": "Edit Parameters",
"label.parameters-as-json": "JSON Parameters",
"label.parameter-query-select": "Get parameters from SQL Query",
"label.error": "Error",
"label.filter-by-notification-config": "Filter by Notification Config",
"label.generated-notification": "Generated Notification",
Expand Down Expand Up @@ -108,4 +109,4 @@
"messages.confirm-duplicate": "Do you want to make a copy of this configuration?",
"button.edit-notification-config": "Edit Notification Config",
"messages.no-events-matching-status": "No events found"
}
}
2 changes: 2 additions & 0 deletions frontend/packages/common/src/types/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -633,6 +633,7 @@ export type NotificationConfigNode = {
configurationData: Scalars['String']['output'];
id: Scalars['String']['output'];
kind: ConfigKind;
parameterQueryId?: Maybe<Scalars['String']['output']>;
parameters: Scalars['String']['output'];
recipientIds: Array<Scalars['String']['output']>;
recipientListIds: Array<Scalars['String']['output']>;
Expand Down Expand Up @@ -950,6 +951,7 @@ export type UpdateNotificationConfigInput = {
configurationData?: InputMaybe<Scalars['String']['input']>;
id: Scalars['String']['input'];
nextDueDatetime?: InputMaybe<Scalars['DateTime']['input']>;
parameterQueryId?: InputMaybe<Scalars['String']['input']>;
parameters?: InputMaybe<Scalars['String']['input']>;
recipientIds?: InputMaybe<Array<Scalars['String']['input']>>;
recipientListIds?: InputMaybe<Array<Scalars['String']['input']>>;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ export const BaseNotificationEditPage = <T extends BaseNotificationConfig>({
allowParameterSets={allowParameterSets}
onUpdateParams={onUpdateParams}
onDeleteParam={onDeleteParam}
onChangeParameterQuery={x => onUpdate({ parameterQueryId: x } as Partial<T>)}
parameterQueryId={draft.parameterQueryId}
/>
<AppBarButtonsPortal sx={{ display: 'flex', gap: '14px' }}>
<BaseButton
Expand Down
Loading

0 comments on commit 0ee9514

Please sign in to comment.