Skip to content

Commit

Permalink
Merge pull request #5347 from msupply-foundation/5305-add-mutate-prog…
Browse files Browse the repository at this point in the history
…ram-indicator-values

5305 add mutate program indicator values
  • Loading branch information
roxy-dao authored Nov 14, 2024
2 parents 6e232d8 + 7c7636c commit 8125541
Show file tree
Hide file tree
Showing 18 changed files with 575 additions and 68 deletions.
13 changes: 0 additions & 13 deletions server/graphql/programs/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,6 @@ use graphql_types::types::program_enrolment::ProgramEnrolmentSortInput;
use graphql_types::types::program_enrolment::ProgramEventFilterInput;
use graphql_types::types::program_event::ProgramEventResponse;
use graphql_types::types::program_event::ProgramEventSortInput;
use graphql_types::types::program_indicator::ProgramIndicatorFilterInput;
use graphql_types::types::program_indicator::ProgramIndicatorResponse;
use graphql_types::types::program_indicator::ProgramIndicatorSortInput;
use graphql_types::types::vaccination::VaccinationNode;
use mutations::allocate_number::allocate_program_number;
use mutations::allocate_number::AllocateProgramNumberInput;
Expand Down Expand Up @@ -311,16 +308,6 @@ impl ProgramsQueries {
) -> Result<VaccinationCardResponse> {
vaccination_card(ctx, store_id, program_enrolment_id)
}

pub async fn program_indicators(
&self,
ctx: &Context<'_>,
store_id: String,
sort: Option<ProgramIndicatorSortInput>,
filter: Option<ProgramIndicatorFilterInput>,
) -> Result<ProgramIndicatorResponse> {
program_indicators(ctx, store_id, sort, filter)
}
}

#[derive(Default, Clone)]
Expand Down
2 changes: 0 additions & 2 deletions server/graphql/programs/src/queries/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,3 @@ pub use self::program::*;
pub use self::r_and_r_form::*;
pub mod vaccination;
pub use self::vaccination::*;
pub mod program_indicator;
pub use self::program_indicator::*;
27 changes: 27 additions & 0 deletions server/graphql/requisition/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,24 @@
pub mod mutations;
mod program_indicator;
mod program_settings;
mod requisition_queries;
use async_graphql::*;
use graphql_core::pagination::PaginationInput;
use graphql_types::types::program_indicator::{
ProgramIndicatorFilterInput, ProgramIndicatorResponse, ProgramIndicatorSortInput,
};
use graphql_types::types::RequisitionNodeType;
use program_indicator::program_indicators;
use program_settings::{
get_customer_program_requisition_settings, get_supplier_program_requisition_settings,
CustomerProgramRequisitionSettingNode, SupplierProgramRequisitionSettingNode,
};

use self::mutations::{request_requisition, response_requisition};
use self::requisition_queries::*;
use mutations::update_indicator_value::{
self, UpdateIndicatorValueInput, UpdateIndicatorValueResponse,
};
#[derive(Default, Clone)]
pub struct RequisitionQueries;

Expand Down Expand Up @@ -61,6 +69,16 @@ impl RequisitionQueries {
) -> Result<Vec<CustomerProgramRequisitionSettingNode>> {
get_customer_program_requisition_settings(ctx, &store_id)
}

pub async fn program_indicators(
&self,
ctx: &Context<'_>,
store_id: String,
sort: Option<ProgramIndicatorSortInput>,
filter: Option<ProgramIndicatorFilterInput>,
) -> Result<ProgramIndicatorResponse> {
program_indicators(ctx, store_id, sort, filter)
}
}

#[derive(Default, Clone)]
Expand Down Expand Up @@ -188,6 +206,15 @@ impl RequisitionMutations {
ctx, &store_id, input,
)
}

pub async fn update_indicator_value(
&self,
ctx: &Context<'_>,
store_id: String,
input: UpdateIndicatorValueInput,
) -> Result<UpdateIndicatorValueResponse> {
update_indicator_value::update(ctx, store_id, input)
}
}

#[cfg(test)]
Expand Down
1 change: 1 addition & 0 deletions server/graphql/requisition/src/mutations/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
pub mod errors;
pub mod request_requisition;
pub mod response_requisition;
pub mod update_indicator_value;
90 changes: 90 additions & 0 deletions server/graphql/requisition/src/mutations/update_indicator_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
use async_graphql::*;
use graphql_core::standard_graphql_error::StandardGraphqlError;
use graphql_core::{
simple_generic_errors::RecordNotFound, standard_graphql_error::validate_auth, ContextExt,
};
use graphql_types::types::program_indicator::IndicatorValueNode;
use service::auth::{Resource, ResourceAccessRequest};
use service::requisition::indicator_value::{UpdateIndicatorValue, UpdateIndicatorValueError};

#[derive(InputObject)]
pub struct UpdateIndicatorValueInput {
pub id: String,
pub value: String,
}

#[derive(Interface)]
#[graphql(name = "UpdateIndicatorValueErrorInterface")]
#[graphql(field(name = "description", ty = "String"))]
pub enum UpdateErrorInterface {
RecordNotFound(RecordNotFound),
}

#[derive(SimpleObject)]
#[graphql(name = "UpdateIndicatorValueError")]
pub struct UpdateError {
pub error: UpdateErrorInterface,
}

#[derive(Union)]
pub enum UpdateIndicatorValueResponse {
Response(IndicatorValueNode),
Error(UpdateError),
}

pub fn update(
ctx: &Context<'_>,
store_id: String,
input: UpdateIndicatorValueInput,
) -> Result<UpdateIndicatorValueResponse> {
let user = validate_auth(
ctx,
&ResourceAccessRequest {
resource: Resource::MutateRequisition,
store_id: Some(store_id.clone()),
},
)?;

let service_provider = ctx.service_provider();
let service_context = service_provider.context(store_id.to_string(), user.user_id)?;

let response = match service_provider
.indicator_value_service
.update_indicator_value(&service_context, input.to_domain())
{
Ok(indicator_value) => {
UpdateIndicatorValueResponse::Response(IndicatorValueNode::from_domain(indicator_value))
}
Err(error) => UpdateIndicatorValueResponse::Error(UpdateError {
error: map_error(error)?,
}),
};

Ok(response)
}

impl UpdateIndicatorValueInput {
pub fn to_domain(self) -> UpdateIndicatorValue {
let UpdateIndicatorValueInput { id, value } = self;
UpdateIndicatorValue { id, value }
}
}

fn map_error(error: UpdateIndicatorValueError) -> Result<UpdateErrorInterface> {
use StandardGraphqlError::*;
let formatted_error = format!("{:?}", error);
let graphql_error = match error {
// Structured Errors
UpdateIndicatorValueError::IndicatorValueDoesNotExist => {
return Ok(UpdateErrorInterface::RecordNotFound(RecordNotFound {}))
}
// Standard graphql errors
UpdateIndicatorValueError::NotThisStoreValue
| UpdateIndicatorValueError::IndicatorColumnDoesNotExist
| UpdateIndicatorValueError::ValueNotCorrectType
| UpdateIndicatorValueError::IndicatorLineDoesNotExist => BadUserInput(formatted_error),
UpdateIndicatorValueError::DatabaseError(_) => InternalError(formatted_error),
};

Err(graphql_error.extend())
}
31 changes: 16 additions & 15 deletions server/graphql/types/src/types/program/program_indicator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,13 @@ use graphql_core::{
loader::{
IndicatorValueLoader, IndicatorValueLoaderInput, IndicatorValuePayload, ProgramByIdLoader,
},
standard_graphql_error::StandardGraphqlError,
ContextExt,
};
use repository::{
EqualFilter, IndicatorColumnRow, IndicatorLineRow, IndicatorValueRow, IndicatorValueType,
ProgramIndicatorFilter, ProgramIndicatorSort, ProgramIndicatorSortField,
};
use service::programs::program_indicator::query::{IndicatorLine, ProgramIndicator};
use service::requisition::program_indicator::query::{IndicatorLine, ProgramIndicator};

use super::program_node::ProgramNode;

Expand Down Expand Up @@ -156,6 +155,10 @@ impl IndicatorLineRowNode {
pub async fn line_number(&self) -> i32 {
self.line.line_number
}

pub async fn value_type(&self) -> Option<IndicatorValueTypeNode> {
IndicatorValueTypeNode::from_domain(&self.line.value_type)
}
}

impl IndicatorColumnNode {
Expand All @@ -175,7 +178,7 @@ impl IndicatorColumnNode {
&self.column.header
}

pub async fn value_type(&self) -> IndicatorValueTypeNode {
pub async fn value_type(&self) -> Option<IndicatorValueTypeNode> {
IndicatorValueTypeNode::from_domain(&self.column.value_type)
}

Expand Down Expand Up @@ -203,15 +206,13 @@ impl IndicatorColumnNode {
&self.column.id,
payload,
))
.await?
.ok_or_else(|| {
StandardGraphqlError::InternalError(format!(
"Cannot find value for column {} with header {}",
&self.line_id, &self.column.id,
))
})?;
.await?;

Ok(Some(IndicatorValueNode::from_domain(result)))
if let Some(value) = result {
Ok(Some(IndicatorValueNode::from_domain(value)))
} else {
Ok(None)
}
}
}

Expand All @@ -222,11 +223,11 @@ pub enum IndicatorValueTypeNode {
}

impl IndicatorValueTypeNode {
pub fn from_domain(r#type: &Option<IndicatorValueType>) -> Self {
pub fn from_domain(r#type: &Option<IndicatorValueType>) -> Option<Self> {
match r#type {
Some(IndicatorValueType::Number) => IndicatorValueTypeNode::Number,
Some(IndicatorValueType::String) => IndicatorValueTypeNode::String,
None => IndicatorValueTypeNode::String,
Some(IndicatorValueType::Number) => Some(IndicatorValueTypeNode::Number),
Some(IndicatorValueType::String) => Some(IndicatorValueTypeNode::String),
None => None,
}
}
}
Expand Down
7 changes: 7 additions & 0 deletions server/repository/src/db_diesel/indicator_value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,13 @@ impl<'a> IndicatorValueRepository<'a> {
.get_result(self.connection.lock().connection())?)
}

pub fn query_one(
&self,
filter: IndicatorValueFilter,
) -> Result<Option<IndicatorValueRow>, RepositoryError> {
Ok(self.query_by_filter(filter)?.pop())
}

pub fn query_by_filter(
&self,
filter: IndicatorValueFilter,
Expand Down
21 changes: 21 additions & 0 deletions server/repository/src/mock/indicator_value.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
use crate::IndicatorValueRow;

use super::{
mock_indicator_column_a, mock_indicator_line_a, mock_period, mock_store_a, mock_store_b,
};

pub fn mock_indicator_value_a() -> IndicatorValueRow {
IndicatorValueRow {
id: String::from("id_a"),
customer_name_link_id: mock_store_b().name_link_id,
store_id: mock_store_a().id,
period_id: mock_period().id,
indicator_line_id: mock_indicator_line_a().id,
indicator_column_id: mock_indicator_column_a().id,
value: String::from("test_value"),
}
}

pub fn mock_indicator_values() -> Vec<IndicatorValueRow> {
vec![mock_indicator_value_a()]
}
Loading

0 comments on commit 8125541

Please sign in to comment.