From 888c82ba2ddc90230e54d8ca1034a3a5cd9402ea Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 25 Oct 2024 15:26:28 +1300 Subject: [PATCH 01/16] Reason option loader --- .../core/src/loader/loader_registry.rs | 6 ++++ server/graphql/core/src/loader/mod.rs | 3 +- .../graphql/core/src/loader/reason_option.rs | 32 +++++++++++++++++++ 3 files changed, 40 insertions(+), 1 deletion(-) create mode 100644 server/graphql/core/src/loader/reason_option.rs diff --git a/server/graphql/core/src/loader/loader_registry.rs b/server/graphql/core/src/loader/loader_registry.rs index 7ee49d5a86..7a38bd0264 100644 --- a/server/graphql/core/src/loader/loader_registry.rs +++ b/server/graphql/core/src/loader/loader_registry.rs @@ -390,6 +390,12 @@ pub async fn get_loaders( }, async_std::task::spawn, )); + loaders.insert(DataLoader::new( + ReasonOptionLoader { + connection_manager: connection_manager.clone(), + }, + async_std::task::spawn, + )); loaders } diff --git a/server/graphql/core/src/loader/mod.rs b/server/graphql/core/src/loader/mod.rs index 06c4d8f167..0f553d774c 100644 --- a/server/graphql/core/src/loader/mod.rs +++ b/server/graphql/core/src/loader/mod.rs @@ -24,6 +24,7 @@ mod name; mod name_row; mod patient; mod program_enrolment; +mod reason_option; mod requisition; mod requisition_line; mod requisition_supply_status; @@ -70,6 +71,7 @@ pub use name::*; pub use name_row::*; pub use patient::*; pub use program_enrolment::*; +pub use reason_option::ReasonOptionLoader; pub use requisition::*; pub use requisition_line::*; pub use requisition_supply_status::*; @@ -87,7 +89,6 @@ pub use vaccine_course::*; pub use vaccine_course_by_program::*; pub use vaccine_course_dose_by_vaccine_course::*; pub use vaccine_course_item_by_vaccine_course::*; - #[derive(Debug, Clone)] /// Sometimes loaders need to take an extra parameter, like store_id or requisition_id /// And in some cases even further parameter is required (lookback date for ItemStats) diff --git a/server/graphql/core/src/loader/reason_option.rs b/server/graphql/core/src/loader/reason_option.rs new file mode 100644 index 0000000000..a119fe3efd --- /dev/null +++ b/server/graphql/core/src/loader/reason_option.rs @@ -0,0 +1,32 @@ +use repository::{ + reason_option::{ReasonOption, ReasonOptionFilter, ReasonOptionRepository}, + EqualFilter, +}; +use repository::{RepositoryError, StorageConnectionManager}; + +use async_graphql::dataloader::*; +use async_graphql::*; +use std::collections::HashMap; + +pub struct ReasonOptionLoader { + pub connection_manager: StorageConnectionManager, +} + +impl Loader for ReasonOptionLoader { + type Value = ReasonOption; + type Error = RepositoryError; + + async fn load(&self, ids: &[String]) -> Result, Self::Error> { + let connection = self.connection_manager.connection()?; + let repo = ReasonOptionRepository::new(&connection); + + let result = repo.query_by_filter( + ReasonOptionFilter::new().id(EqualFilter::equal_any(ids.to_owned())), + )?; + + Ok(result + .into_iter() + .map(|reason_option| (reason_option.reason_option_row.id.clone(), reason_option)) + .collect()) + } +} From 208ad3c728153d372dd4d5a4c6e50ab374d2cd1f Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Fri, 25 Oct 2024 15:27:40 +1300 Subject: [PATCH 02/16] Add AMC and reason to requisition node --- .../types/src/types/requisition_line.rs | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/server/graphql/types/src/types/requisition_line.rs b/server/graphql/types/src/types/requisition_line.rs index dcf441a8d3..6ce4a20b67 100644 --- a/server/graphql/types/src/types/requisition_line.rs +++ b/server/graphql/types/src/types/requisition_line.rs @@ -9,13 +9,14 @@ use service::{item_stats::ItemStats, usize_to_u32, ListResult}; use graphql_core::{ loader::{ InvoiceLineForRequisitionLine, ItemLoader, ItemStatsLoaderInput, ItemsStatsForItemLoader, - LinkedRequisitionLineLoader, RequisitionAndItemId, RequisitionLineSupplyStatusLoader, + LinkedRequisitionLineLoader, ReasonOptionLoader, RequisitionAndItemId, + RequisitionLineSupplyStatusLoader, }, standard_graphql_error::StandardGraphqlError, ContextExt, }; -use super::{InvoiceLineConnector, ItemNode, ItemStatsNode}; +use super::{InvoiceLineConnector, ItemNode, ItemStatsNode, ReasonOptionNode}; #[derive(PartialEq, Debug)] pub struct RequisitionLineNode { @@ -261,6 +262,23 @@ impl RequisitionLineNode { pub async fn option_id(&self) -> &Option { &self.row().option_id } + + pub async fn average_monthly_consumption(&self) -> &f64 { + &self.row().average_monthly_consumption + } + + pub async fn reason(&self, ctx: &Context<'_>) -> Result> { + let loader = ctx.get_loader::>(); + + let reason_option_id = match &self.row().option_id { + Some(reason_option_id) => reason_option_id, + None => return Ok(None), + }; + + let result = loader.load_one(reason_option_id.clone()).await?; + + Ok(result.map(ReasonOptionNode::from_domain)) + } } impl RequisitionLineNode { From dfe3d128950c943babc0be0d505eddb8ea99cac1 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Tue, 29 Oct 2024 15:57:27 +1300 Subject: [PATCH 03/16] Expose available stock on hand --- .../src/mutations/response_requisition_line/insert.rs | 6 +++--- .../src/mutations/response_requisition_line/update.rs | 8 ++++---- server/graphql/types/src/types/requisition_line.rs | 4 ++++ .../response_requisition_line/insert/generate.rs | 6 +++--- .../response_requisition_line/insert/mod.rs | 4 ++-- .../response_requisition_line/update.rs | 10 +++++----- 6 files changed, 21 insertions(+), 17 deletions(-) diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs index ab51aa4921..69ec645f11 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs @@ -22,7 +22,7 @@ pub struct InsertInput { pub id: String, pub item_id: String, pub requisition_id: String, - pub their_stock_on_hand: Option, + pub initial_stock_on_hand: Option, pub supply_quantity: Option, pub requested_quantity: Option, pub comment: Option, @@ -87,7 +87,7 @@ impl InsertInput { id, item_id, requisition_id, - their_stock_on_hand, + initial_stock_on_hand, supply_quantity, requested_quantity, comment, @@ -97,7 +97,7 @@ impl InsertInput { id, item_id, requisition_id, - their_stock_on_hand, + initial_stock_on_hand, supply_quantity, requested_quantity, comment, diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs index b184040db3..126b506093 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs @@ -19,7 +19,7 @@ pub struct UpdateInput { pub id: String, pub supply_quantity: Option, pub requested_quantity: Option, - pub their_stock_on_hand: Option, + pub initial_stock_on_hand: Option, pub comment: Option, } @@ -77,7 +77,7 @@ impl UpdateInput { id, supply_quantity, requested_quantity, - their_stock_on_hand, + initial_stock_on_hand, comment, } = self; @@ -85,7 +85,7 @@ impl UpdateInput { id, supply_quantity, requested_quantity, - their_stock_on_hand, + initial_stock_on_hand, comment, } } @@ -330,7 +330,7 @@ mod test { id: "update line id input".to_string(), supply_quantity: Some(1.0), requested_quantity: None, - their_stock_on_hand: None, + initial_stock_on_hand: None, comment: Some("comment".to_string()), } ); diff --git a/server/graphql/types/src/types/requisition_line.rs b/server/graphql/types/src/types/requisition_line.rs index 6ce4a20b67..ba3c4d2dcc 100644 --- a/server/graphql/types/src/types/requisition_line.rs +++ b/server/graphql/types/src/types/requisition_line.rs @@ -279,6 +279,10 @@ impl RequisitionLineNode { Ok(result.map(ReasonOptionNode::from_domain)) } + + pub async fn available_stock_on_hand(&self) -> &f64 { + &self.row().available_stock_on_hand + } } impl RequisitionLineNode { diff --git a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs index 7b90b14125..22dd6fce2a 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs @@ -14,7 +14,7 @@ pub fn generate( id, requisition_id: _, item_id, - their_stock_on_hand, + initial_stock_on_hand, requested_quantity, supply_quantity, comment, @@ -26,8 +26,8 @@ pub fn generate( .ok_or(OutError::CannotFindItemStatusForRequisitionLine)?; new_requisition_line.id = id; - new_requisition_line.initial_stock_on_hand_units = their_stock_on_hand.unwrap_or(0.0); - new_requisition_line.available_stock_on_hand = their_stock_on_hand.unwrap_or(0.0); + new_requisition_line.initial_stock_on_hand_units = initial_stock_on_hand.unwrap_or(0.0); + new_requisition_line.available_stock_on_hand = initial_stock_on_hand.unwrap_or(0.0); new_requisition_line.supply_quantity = supply_quantity.unwrap_or(0.0); new_requisition_line.requested_quantity = requested_quantity.unwrap_or(0.0); new_requisition_line.comment = comment.or(new_requisition_line.comment); diff --git a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs index af4df0f5d2..a476d049d8 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs @@ -11,7 +11,7 @@ pub struct InsertResponseRequisitionLine { pub id: String, pub item_id: String, pub requisition_id: String, - pub their_stock_on_hand: Option, + pub initial_stock_on_hand: Option, pub requested_quantity: Option, pub supply_quantity: Option, pub comment: Option, @@ -250,7 +250,7 @@ mod test { requisition_id: new_response_requisition().id, id: "new requisition line id".to_string(), item_id: test_item_stats::item2().id, - their_stock_on_hand: Some(10.0), + initial_stock_on_hand: Some(10.0), requested_quantity: Some(10.0), supply_quantity: Some(20.0), comment: Some("comment".to_string()), diff --git a/server/service/src/requisition_line/response_requisition_line/update.rs b/server/service/src/requisition_line/response_requisition_line/update.rs index b76d6db039..ba3a649b7b 100644 --- a/server/service/src/requisition_line/response_requisition_line/update.rs +++ b/server/service/src/requisition_line/response_requisition_line/update.rs @@ -18,7 +18,7 @@ pub struct UpdateResponseRequisitionLine { pub id: String, pub supply_quantity: Option, pub requested_quantity: Option, - pub their_stock_on_hand: Option, + pub initial_stock_on_hand: Option, pub comment: Option, } @@ -104,16 +104,16 @@ fn generate( supply_quantity: updated_supply_quantity, comment: updated_comment, requested_quantity: updated_requested_quantity, - their_stock_on_hand: updated_their_stock_on_hand, + initial_stock_on_hand: updated_initial_stock_on_hand, }: UpdateResponseRequisitionLine, ) -> (Option, RequisitionLineRow) { let requisition_line_row = inline_edit(&existing, |mut u| { u.supply_quantity = updated_supply_quantity.unwrap_or(u.supply_quantity); u.requested_quantity = updated_requested_quantity.unwrap_or(u.requested_quantity); u.initial_stock_on_hand_units = - updated_their_stock_on_hand.unwrap_or(u.initial_stock_on_hand_units); + updated_initial_stock_on_hand.unwrap_or(u.initial_stock_on_hand_units); u.available_stock_on_hand = - updated_their_stock_on_hand.unwrap_or(u.available_stock_on_hand); + updated_initial_stock_on_hand.unwrap_or(u.available_stock_on_hand); u.comment = updated_comment.or(u.comment); u }); @@ -246,7 +246,7 @@ mod test { supply_quantity: Some(99.0), comment: Some("comment".to_string()), requested_quantity: Some(99.0), - their_stock_on_hand: Some(99.0), + initial_stock_on_hand: Some(99.0), }, ) .unwrap(); From 97a94b21387145cd78307d895d3da36c73bc4aa2 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 10:20:18 +1300 Subject: [PATCH 04/16] Don't update available_soh if there is a linked requisition --- .../mutations/response_requisition_line/insert.rs | 6 +++--- .../mutations/response_requisition_line/update.rs | 8 ++++---- .../response_requisition_line/insert/generate.rs | 7 +++++-- .../response_requisition_line/insert/mod.rs | 4 ++-- .../response_requisition_line/update.rs | 12 ++++++------ 5 files changed, 20 insertions(+), 17 deletions(-) diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs index 8540badd30..b29ba1494c 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs @@ -22,7 +22,7 @@ pub struct InsertInput { pub id: String, pub item_id: String, pub requisition_id: String, - pub initial_stock_on_hand: Option, + pub stock_on_hand: Option, pub supply_quantity: Option, pub requested_quantity: Option, pub comment: Option, @@ -87,7 +87,7 @@ impl InsertInput { id, item_id, requisition_id, - initial_stock_on_hand, + stock_on_hand, supply_quantity, requested_quantity, comment, @@ -97,7 +97,7 @@ impl InsertInput { id, item_id, requisition_id, - initial_stock_on_hand, + stock_on_hand, supply_quantity, requested_quantity, comment, diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs index 126b506093..21298f94bf 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs @@ -19,7 +19,7 @@ pub struct UpdateInput { pub id: String, pub supply_quantity: Option, pub requested_quantity: Option, - pub initial_stock_on_hand: Option, + pub stock_on_hand: Option, pub comment: Option, } @@ -77,7 +77,7 @@ impl UpdateInput { id, supply_quantity, requested_quantity, - initial_stock_on_hand, + stock_on_hand, comment, } = self; @@ -85,7 +85,7 @@ impl UpdateInput { id, supply_quantity, requested_quantity, - initial_stock_on_hand, + stock_on_hand: stock_on_hand, comment, } } @@ -330,7 +330,7 @@ mod test { id: "update line id input".to_string(), supply_quantity: Some(1.0), requested_quantity: None, - initial_stock_on_hand: None, + stock_on_hand: None, comment: Some("comment".to_string()), } ); diff --git a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs index 22dd6fce2a..67e258b004 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs @@ -14,7 +14,7 @@ pub fn generate( id, requisition_id: _, item_id, - initial_stock_on_hand, + stock_on_hand: initial_stock_on_hand, requested_quantity, supply_quantity, comment, @@ -26,8 +26,11 @@ pub fn generate( .ok_or(OutError::CannotFindItemStatusForRequisitionLine)?; new_requisition_line.id = id; + if requisition_row.linked_requisition_id.is_none() { + new_requisition_line.available_stock_on_hand = + initial_stock_on_hand.unwrap_or(new_requisition_line.available_stock_on_hand); + } new_requisition_line.initial_stock_on_hand_units = initial_stock_on_hand.unwrap_or(0.0); - new_requisition_line.available_stock_on_hand = initial_stock_on_hand.unwrap_or(0.0); new_requisition_line.supply_quantity = supply_quantity.unwrap_or(0.0); new_requisition_line.requested_quantity = requested_quantity.unwrap_or(0.0); new_requisition_line.comment = comment.or(new_requisition_line.comment); diff --git a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs index a476d049d8..df0d81b692 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs @@ -11,7 +11,7 @@ pub struct InsertResponseRequisitionLine { pub id: String, pub item_id: String, pub requisition_id: String, - pub initial_stock_on_hand: Option, + pub stock_on_hand: Option, pub requested_quantity: Option, pub supply_quantity: Option, pub comment: Option, @@ -250,7 +250,7 @@ mod test { requisition_id: new_response_requisition().id, id: "new requisition line id".to_string(), item_id: test_item_stats::item2().id, - initial_stock_on_hand: Some(10.0), + stock_on_hand: Some(10.0), requested_quantity: Some(10.0), supply_quantity: Some(20.0), comment: Some("comment".to_string()), diff --git a/server/service/src/requisition_line/response_requisition_line/update.rs b/server/service/src/requisition_line/response_requisition_line/update.rs index ba3a649b7b..c00c97dd77 100644 --- a/server/service/src/requisition_line/response_requisition_line/update.rs +++ b/server/service/src/requisition_line/response_requisition_line/update.rs @@ -18,7 +18,7 @@ pub struct UpdateResponseRequisitionLine { pub id: String, pub supply_quantity: Option, pub requested_quantity: Option, - pub initial_stock_on_hand: Option, + pub stock_on_hand: Option, pub comment: Option, } @@ -104,16 +104,16 @@ fn generate( supply_quantity: updated_supply_quantity, comment: updated_comment, requested_quantity: updated_requested_quantity, - initial_stock_on_hand: updated_initial_stock_on_hand, + stock_on_hand: updated_stock_on_hand, }: UpdateResponseRequisitionLine, ) -> (Option, RequisitionLineRow) { let requisition_line_row = inline_edit(&existing, |mut u| { u.supply_quantity = updated_supply_quantity.unwrap_or(u.supply_quantity); u.requested_quantity = updated_requested_quantity.unwrap_or(u.requested_quantity); u.initial_stock_on_hand_units = - updated_initial_stock_on_hand.unwrap_or(u.initial_stock_on_hand_units); - u.available_stock_on_hand = - updated_initial_stock_on_hand.unwrap_or(u.available_stock_on_hand); + updated_stock_on_hand.unwrap_or(u.initial_stock_on_hand_units); + u.available_stock_on_hand = updated_stock_on_hand.unwrap_or(0.0); + u.comment = updated_comment.or(u.comment); u }); @@ -246,7 +246,7 @@ mod test { supply_quantity: Some(99.0), comment: Some("comment".to_string()), requested_quantity: Some(99.0), - initial_stock_on_hand: Some(99.0), + stock_on_hand: Some(99.0), }, ) .unwrap(); From d5ee2262e9a4f1e6877f0bb3cec09e03ee19f94b Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 11:40:13 +1300 Subject: [PATCH 05/16] Item check returning item --- server/service/src/item/item.rs | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/server/service/src/item/item.rs b/server/service/src/item/item.rs index 0a8cd5dabc..d79bbfb8d2 100644 --- a/server/service/src/item/item.rs +++ b/server/service/src/item/item.rs @@ -36,3 +36,16 @@ pub fn check_item_exists( )?; Ok(count > 0) } + +pub fn check_item_exists_return_item( + connection: &StorageConnection, + store_id: String, + item_id: &str, +) -> Result, RepositoryError> { + Ok(ItemRepository::new(connection) + .query_by_filter( + ItemFilter::new().id(EqualFilter::equal_to(item_id)), + Some(store_id), + )? + .pop()) +} From 9e95fabc28d09536861c689c598d224809353744 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:05:50 +1300 Subject: [PATCH 06/16] New fields for inserting response requisition line --- .../response_requisition_line/insert.rs | 37 ++++++++-- .../insert/generate.rs | 71 ++++++++++++------- .../response_requisition_line/insert/mod.rs | 20 ++++-- .../insert/validate.rs | 13 ++-- 4 files changed, 99 insertions(+), 42 deletions(-) diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs index b29ba1494c..fc16e687de 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/insert.rs @@ -22,10 +22,19 @@ pub struct InsertInput { pub id: String, pub item_id: String, pub requisition_id: String, - pub stock_on_hand: Option, pub supply_quantity: Option, - pub requested_quantity: Option, pub comment: Option, + // Manual Requisition fields + pub requested_quantity: Option, + pub stock_on_hand: Option, + pub average_monthly_consumption: Option, + pub incoming_units: Option, + pub outgoing_units: Option, + pub loss_in_units: Option, + pub addition_in_units: Option, + pub expiring_units: Option, + pub days_out_of_stock: Option, + pub option_id: Option, } #[derive(Interface)] @@ -87,20 +96,36 @@ impl InsertInput { id, item_id, requisition_id, - stock_on_hand, supply_quantity, - requested_quantity, comment, + stock_on_hand, + requested_quantity, + average_monthly_consumption, + incoming_units, + outgoing_units, + loss_in_units, + addition_in_units, + expiring_units, + days_out_of_stock, + option_id, } = self; ServiceInput { id, item_id, requisition_id, - stock_on_hand, supply_quantity, - requested_quantity, comment, + stock_on_hand, + requested_quantity, + average_monthly_consumption, + incoming_units, + outgoing_units, + loss_in_units, + addition_in_units, + expiring_units, + days_out_of_stock, + option_id, } } } diff --git a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs index 67e258b004..edd7b66e6d 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/generate.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/generate.rs @@ -1,39 +1,62 @@ -use repository::{RequisitionLineRow, RequisitionRow}; +use chrono::Utc; +use repository::{ItemRow, RequisitionLineRow, RequisitionRow}; -use crate::{ - requisition::request_requisition::generate_requisition_lines, service_provider::ServiceContext, +use crate::requisition::request_requisition::{ + generate_suggested_quantity, GenerateSuggestedQuantity, }; -use super::{InsertResponseRequisitionLine, OutError}; +use super::InsertResponseRequisitionLine; pub fn generate( - ctx: &ServiceContext, - store_id: &str, requisition_row: RequisitionRow, + item_row: ItemRow, InsertResponseRequisitionLine { id, requisition_id: _, - item_id, - stock_on_hand: initial_stock_on_hand, - requested_quantity, + item_id: _, supply_quantity, comment, + stock_on_hand, + requested_quantity, + average_monthly_consumption, + incoming_units, + outgoing_units, + loss_in_units, + addition_in_units, + expiring_units, + days_out_of_stock, + option_id, }: InsertResponseRequisitionLine, -) -> Result { - let mut new_requisition_line = - generate_requisition_lines(ctx, store_id, &requisition_row, vec![item_id])? - .pop() - .ok_or(OutError::CannotFindItemStatusForRequisitionLine)?; +) -> RequisitionLineRow { + let suggested_quantity = generate_suggested_quantity(GenerateSuggestedQuantity { + average_monthly_consumption: average_monthly_consumption.unwrap_or(0.0), + available_stock_on_hand: stock_on_hand.unwrap_or(0.0), + min_months_of_stock: requisition_row.min_months_of_stock, + max_months_of_stock: requisition_row.max_months_of_stock, + }); - new_requisition_line.id = id; - if requisition_row.linked_requisition_id.is_none() { - new_requisition_line.available_stock_on_hand = - initial_stock_on_hand.unwrap_or(new_requisition_line.available_stock_on_hand); + RequisitionLineRow { + id: id.clone(), + item_link_id: item_row.id, + item_name: item_row.name, + requisition_id: requisition_row.id, + requested_quantity: requested_quantity.unwrap_or(0.0), + initial_stock_on_hand_units: stock_on_hand.unwrap_or(0.0), + available_stock_on_hand: stock_on_hand.unwrap_or(0.0), + average_monthly_consumption: average_monthly_consumption.unwrap_or(0.0), + supply_quantity: supply_quantity.unwrap_or(0.0), + incoming_units: incoming_units.unwrap_or(0.0), + outgoing_units: outgoing_units.unwrap_or(0.0), + loss_in_units: loss_in_units.unwrap_or(0.0), + addition_in_units: addition_in_units.unwrap_or(0.0), + expiring_units: expiring_units.unwrap_or(0.0), + days_out_of_stock: days_out_of_stock.unwrap_or(0.0), + suggested_quantity, + option_id: option_id.clone(), + comment, + snapshot_datetime: Some(Utc::now().naive_utc()), + // Default + approved_quantity: 0.0, + approval_comment: None, } - new_requisition_line.initial_stock_on_hand_units = initial_stock_on_hand.unwrap_or(0.0); - new_requisition_line.supply_quantity = supply_quantity.unwrap_or(0.0); - new_requisition_line.requested_quantity = requested_quantity.unwrap_or(0.0); - new_requisition_line.comment = comment.or(new_requisition_line.comment); - - Ok(new_requisition_line) } diff --git a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs index df0d81b692..265e8106a5 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/mod.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/mod.rs @@ -11,10 +11,19 @@ pub struct InsertResponseRequisitionLine { pub id: String, pub item_id: String, pub requisition_id: String, - pub stock_on_hand: Option, - pub requested_quantity: Option, pub supply_quantity: Option, pub comment: Option, + // Manual Requisition fields + pub requested_quantity: Option, + pub stock_on_hand: Option, + pub average_monthly_consumption: Option, + pub incoming_units: Option, + pub outgoing_units: Option, + pub loss_in_units: Option, + pub addition_in_units: Option, + pub expiring_units: Option, + pub days_out_of_stock: Option, + pub option_id: Option, } #[derive(Debug, PartialEq)] @@ -43,8 +52,8 @@ pub fn insert_response_requisition_line( let requisition_line = ctx .connection .transaction_sync(|connection| { - let requisition_row = validate(connection, &ctx.store_id, &input)?; - let new_requisition_line_row = generate(ctx, &ctx.store_id, requisition_row, input)?; + let (requisition_row, item_row) = validate(connection, &ctx.store_id, &input)?; + let new_requisition_line_row = generate(requisition_row, item_row, input); RequisitionLineRowRepository::new(connection).upsert_one(&new_requisition_line_row)?; @@ -254,6 +263,7 @@ mod test { requested_quantity: Some(10.0), supply_quantity: Some(20.0), comment: Some("comment".to_string()), + ..Default::default() }, ) .unwrap(); @@ -270,7 +280,7 @@ mod test { u.requested_quantity = 10.0; u.initial_stock_on_hand_units = 10.0; u.available_stock_on_hand = 10.0; - u.average_monthly_consumption = test_item_stats::item2_amc_3_months(); + u.average_monthly_consumption = 0.0; u.comment = Some("comment".to_string()); u }) diff --git a/server/service/src/requisition_line/response_requisition_line/insert/validate.rs b/server/service/src/requisition_line/response_requisition_line/insert/validate.rs index f7096eee4a..6249f57ba8 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/validate.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/validate.rs @@ -1,7 +1,7 @@ -use repository::{RequisitionRow, RequisitionStatus, RequisitionType, StorageConnection}; +use repository::{ItemRow, RequisitionRow, RequisitionStatus, RequisitionType, StorageConnection}; use crate::{ - item::check_item_exists, + item::check_item_exists_return_item, requisition::common::check_requisition_row_exists, requisition_line::common::{check_item_exists_in_requisition, check_requisition_line_exists}, }; @@ -12,7 +12,7 @@ pub fn validate( connection: &StorageConnection, store_id: &str, input: &InsertResponseRequisitionLine, -) -> Result { +) -> Result<(RequisitionRow, ItemRow), OutError> { if (check_requisition_line_exists(connection, &input.id)?).is_some() { return Err(OutError::RequisitionLineAlreadyExists); } @@ -42,9 +42,8 @@ pub fn validate( return Err(OutError::ItemAlreadyExistInRequisition); } - if !check_item_exists(connection, store_id.to_string(), &input.item_id)? { - return Err(OutError::ItemDoesNotExist); - } + let item = check_item_exists_return_item(connection, store_id.to_string(), &input.item_id)? + .ok_or(OutError::ItemDoesNotExist)?; - Ok(requisition_row) + Ok((requisition_row, item.item_row)) } From f1a0bf71c7fc14ac30316107d1cedb34734bd062 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:06:39 +1300 Subject: [PATCH 07/16] New requisition fields for update response requisition line --- .../response_requisition_line/update.rs | 42 +++++++++++++++++-- .../response_requisition_line/update.rs | 36 ++++++++++++++-- 2 files changed, 71 insertions(+), 7 deletions(-) diff --git a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs index 21298f94bf..a98ca6df2e 100644 --- a/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs +++ b/server/graphql/requisition_line/src/mutations/response_requisition_line/update.rs @@ -18,9 +18,18 @@ use service::{ pub struct UpdateInput { pub id: String, pub supply_quantity: Option, + pub comment: Option, + // Manual Requisition fields pub requested_quantity: Option, pub stock_on_hand: Option, - pub comment: Option, + pub average_monthly_consumption: Option, + pub incoming_units: Option, + pub outgoing_units: Option, + pub loss_in_units: Option, + pub addition_in_units: Option, + pub expiring_units: Option, + pub days_out_of_stock: Option, + pub option_id: Option, } #[derive(Interface)] @@ -79,14 +88,30 @@ impl UpdateInput { requested_quantity, stock_on_hand, comment, + average_monthly_consumption, + incoming_units, + outgoing_units, + loss_in_units, + addition_in_units, + expiring_units, + days_out_of_stock, + option_id, } = self; ServiceInput { id, supply_quantity, requested_quantity, - stock_on_hand: stock_on_hand, + stock_on_hand, comment, + average_monthly_consumption, + incoming_units, + outgoing_units, + loss_in_units, + addition_in_units, + expiring_units, + days_out_of_stock, + option_id, } } } @@ -332,6 +357,7 @@ mod test { requested_quantity: None, stock_on_hand: None, comment: Some("comment".to_string()), + ..Default::default() } ); Ok(RequisitionLine { @@ -346,8 +372,16 @@ mod test { "id": "update line id input", "supplyQuantity": 1, "requestedQuantity": null, - "theirStockOnHand": null, - "comment": "comment" + "stockOnHand": null, + "comment": "comment", + "averageMonthlyConsumption": null, + "incomingUnits": null, + "outgoingUnits": null, + "lossInUnits": null, + "additionInUnits": null, + "expiringUnits": null, + "daysOutOfStock": null, + "optionId": null }, "storeId": "store_a" }); diff --git a/server/service/src/requisition_line/response_requisition_line/update.rs b/server/service/src/requisition_line/response_requisition_line/update.rs index c00c97dd77..752168dd34 100644 --- a/server/service/src/requisition_line/response_requisition_line/update.rs +++ b/server/service/src/requisition_line/response_requisition_line/update.rs @@ -17,9 +17,18 @@ use util::inline_edit; pub struct UpdateResponseRequisitionLine { pub id: String, pub supply_quantity: Option, + pub comment: Option, + //Manual Requisition pub requested_quantity: Option, pub stock_on_hand: Option, - pub comment: Option, + pub average_monthly_consumption: Option, + pub incoming_units: Option, + pub outgoing_units: Option, + pub loss_in_units: Option, + pub addition_in_units: Option, + pub expiring_units: Option, + pub days_out_of_stock: Option, + pub option_id: Option, } #[derive(Debug, PartialEq)] @@ -105,16 +114,36 @@ fn generate( comment: updated_comment, requested_quantity: updated_requested_quantity, stock_on_hand: updated_stock_on_hand, + average_monthly_consumption: updated_average_monthly_consumption, + incoming_units: updated_incoming_units, + outgoing_units: updated_outgoing_units, + loss_in_units: updated_loss_in_units, + addition_in_units: updated_addition_in_units, + expiring_units: updated_expiring_units, + days_out_of_stock: updated_days_out_of_stock, + option_id: updated_option_id, }: UpdateResponseRequisitionLine, ) -> (Option, RequisitionLineRow) { let requisition_line_row = inline_edit(&existing, |mut u| { u.supply_quantity = updated_supply_quantity.unwrap_or(u.supply_quantity); + u.comment = updated_comment.or(u.comment); + if existing_requisition_row.linked_requisition_id.is_none() { + u.available_stock_on_hand = updated_stock_on_hand.unwrap_or(0.0); + u.average_monthly_consumption = + updated_average_monthly_consumption.unwrap_or(u.average_monthly_consumption); + } + // Manual Requisition fields u.requested_quantity = updated_requested_quantity.unwrap_or(u.requested_quantity); u.initial_stock_on_hand_units = updated_stock_on_hand.unwrap_or(u.initial_stock_on_hand_units); - u.available_stock_on_hand = updated_stock_on_hand.unwrap_or(0.0); + u.incoming_units = updated_incoming_units.unwrap_or(u.incoming_units); + u.outgoing_units = updated_outgoing_units.unwrap_or(u.outgoing_units); + u.loss_in_units = updated_loss_in_units.unwrap_or(u.loss_in_units); + u.addition_in_units = updated_addition_in_units.unwrap_or(u.addition_in_units); + u.expiring_units = updated_expiring_units.unwrap_or(u.expiring_units); + u.days_out_of_stock = updated_days_out_of_stock.unwrap_or(u.days_out_of_stock); + u.option_id = updated_option_id.or(u.option_id); - u.comment = updated_comment.or(u.comment); u }); @@ -247,6 +276,7 @@ mod test { comment: Some("comment".to_string()), requested_quantity: Some(99.0), stock_on_hand: Some(99.0), + ..Default::default() }, ) .unwrap(); From cb59d69b4d1528c5d399f1d72932a2985b26df50 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:08:38 +1300 Subject: [PATCH 08/16] Expose new requisition line fields --- client/packages/common/src/types/schema.ts | 23 +++++++++++++++++-- .../api/operations.generated.ts | 23 ++++++++++++++++--- .../api/operations.graphql | 18 +++++++++++++++ 3 files changed, 59 insertions(+), 5 deletions(-) diff --git a/client/packages/common/src/types/schema.ts b/client/packages/common/src/types/schema.ts index 00934f8f3d..3903ba4f92 100644 --- a/client/packages/common/src/types/schema.ts +++ b/client/packages/common/src/types/schema.ts @@ -2941,13 +2941,21 @@ export type InsertResponseRequisitionLineErrorInterface = { }; export type InsertResponseRequisitionLineInput = { + additionInUnits?: InputMaybe; + averageMonthlyConsumption?: InputMaybe; comment?: InputMaybe; + daysOutOfStock?: InputMaybe; + expiringUnits?: InputMaybe; id: Scalars['String']['input']; + incomingUnits?: InputMaybe; itemId: Scalars['String']['input']; + lossInUnits?: InputMaybe; + optionId?: InputMaybe; + outgoingUnits?: InputMaybe; requestedQuantity?: InputMaybe; requisitionId: Scalars['String']['input']; + stockOnHand?: InputMaybe; supplyQuantity?: InputMaybe; - theirStockOnHand?: InputMaybe; }; export type InsertResponseRequisitionLineResponse = InsertResponseRequisitionLineError | RequisitionLineNode; @@ -6460,6 +6468,8 @@ export type RequisitionLineNode = { alreadyIssued: Scalars['Float']['output']; approvalComment?: Maybe; approvedQuantity: Scalars['Float']['output']; + availableStockOnHand: Scalars['Float']['output']; + averageMonthlyConsumption: Scalars['Float']['output']; comment?: Maybe; daysOutOfStock: Scalars['Float']['output']; expiringUnits: Scalars['Float']['output']; @@ -6482,6 +6492,7 @@ export type RequisitionLineNode = { /** OutboundShipment lines linked to requisitions line */ outboundShipmentLines: InvoiceLineConnector; outgoingUnits: Scalars['Float']['output']; + reason?: Maybe; /** * Quantity remaining to supply * supplyQuantity minus all (including unallocated) linked invoice lines numberOfPacks * packSize @@ -8131,11 +8142,19 @@ export type UpdateResponseRequisitionLineErrorInterface = { }; export type UpdateResponseRequisitionLineInput = { + additionInUnits?: InputMaybe; + averageMonthlyConsumption?: InputMaybe; comment?: InputMaybe; + daysOutOfStock?: InputMaybe; + expiringUnits?: InputMaybe; id: Scalars['String']['input']; + incomingUnits?: InputMaybe; + lossInUnits?: InputMaybe; + optionId?: InputMaybe; + outgoingUnits?: InputMaybe; requestedQuantity?: InputMaybe; + stockOnHand?: InputMaybe; supplyQuantity?: InputMaybe; - theirStockOnHand?: InputMaybe; }; export type UpdateResponseRequisitionLineResponse = RequisitionLineNode | UpdateResponseRequisitionLineError; diff --git a/client/packages/requisitions/src/ResponseRequisition/api/operations.generated.ts b/client/packages/requisitions/src/ResponseRequisition/api/operations.generated.ts index 6ce6515abc..fb6c492de8 100644 --- a/client/packages/requisitions/src/ResponseRequisition/api/operations.generated.ts +++ b/client/packages/requisitions/src/ResponseRequisition/api/operations.generated.ts @@ -12,9 +12,9 @@ export type UpdateResponseMutationVariables = Types.Exact<{ export type UpdateResponseMutation = { __typename: 'Mutations', updateResponseRequisition: { __typename: 'RequisitionNode', id: string } | { __typename: 'UpdateResponseRequisitionError' } }; -export type ResponseLineFragment = { __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number } } | null }; +export type ResponseLineFragment = { __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, initialStockOnHandUnits: number, incomingUnits: number, outgoingUnits: number, lossInUnits: number, additionInUnits: number, expiringUnits: number, daysOutOfStock: number, optionId?: string | null, averageMonthlyConsumption: number, suggestedQuantity: number, availableStockOnHand: number, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, averageMonthlyConsumption: number, availableMonthsOfStockOnHand?: number | null } } | null, reason?: { __typename: 'ReasonOptionNode', id: string, reason: string } | null }; -export type ResponseFragment = { __typename: 'RequisitionNode', id: string, type: Types.RequisitionNodeType, status: Types.RequisitionNodeStatus, createdDatetime: string, sentDatetime?: string | null, finalisedDatetime?: string | null, requisitionNumber: number, colour?: string | null, theirReference?: string | null, comment?: string | null, otherPartyName: string, otherPartyId: string, maxMonthsOfStock: number, minMonthsOfStock: number, approvalStatus: Types.RequisitionNodeApprovalStatus, programName?: string | null, orderType?: string | null, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, shipments: { __typename: 'InvoiceConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceNode', id: string, invoiceNumber: number, createdDatetime: string, user?: { __typename: 'UserNode', username: string } | null }> }, linesRemainingToSupply: { __typename: 'RequisitionLineConnector', totalCount: number }, lines: { __typename: 'RequisitionLineConnector', totalCount: number, nodes: Array<{ __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number } } | null }> }, otherParty: { __typename: 'NameNode', id: string, code: string, isCustomer: boolean, isSupplier: boolean, isOnHold: boolean, name: string, store?: { __typename: 'StoreNode', id: string, code: string } | null }, period?: { __typename: 'PeriodNode', name: string, startDate: string, endDate: string } | null, linkedRequisition?: { __typename: 'RequisitionNode', id: string } | null }; +export type ResponseFragment = { __typename: 'RequisitionNode', id: string, type: Types.RequisitionNodeType, status: Types.RequisitionNodeStatus, createdDatetime: string, sentDatetime?: string | null, finalisedDatetime?: string | null, requisitionNumber: number, colour?: string | null, theirReference?: string | null, comment?: string | null, otherPartyName: string, otherPartyId: string, maxMonthsOfStock: number, minMonthsOfStock: number, approvalStatus: Types.RequisitionNodeApprovalStatus, programName?: string | null, orderType?: string | null, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, shipments: { __typename: 'InvoiceConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceNode', id: string, invoiceNumber: number, createdDatetime: string, user?: { __typename: 'UserNode', username: string } | null }> }, linesRemainingToSupply: { __typename: 'RequisitionLineConnector', totalCount: number }, lines: { __typename: 'RequisitionLineConnector', totalCount: number, nodes: Array<{ __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, initialStockOnHandUnits: number, incomingUnits: number, outgoingUnits: number, lossInUnits: number, additionInUnits: number, expiringUnits: number, daysOutOfStock: number, optionId?: string | null, averageMonthlyConsumption: number, suggestedQuantity: number, availableStockOnHand: number, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, averageMonthlyConsumption: number, availableMonthsOfStockOnHand?: number | null } } | null, reason?: { __typename: 'ReasonOptionNode', id: string, reason: string } | null }> }, otherParty: { __typename: 'NameNode', id: string, code: string, isCustomer: boolean, isSupplier: boolean, isOnHold: boolean, name: string, store?: { __typename: 'StoreNode', id: string, code: string } | null }, period?: { __typename: 'PeriodNode', name: string, startDate: string, endDate: string } | null, linkedRequisition?: { __typename: 'RequisitionNode', id: string } | null }; export type ResponseByNumberQueryVariables = Types.Exact<{ storeId: Types.Scalars['String']['input']; @@ -22,7 +22,7 @@ export type ResponseByNumberQueryVariables = Types.Exact<{ }>; -export type ResponseByNumberQuery = { __typename: 'Queries', requisitionByNumber: { __typename: 'RecordNotFound' } | { __typename: 'RequisitionNode', id: string, type: Types.RequisitionNodeType, status: Types.RequisitionNodeStatus, createdDatetime: string, sentDatetime?: string | null, finalisedDatetime?: string | null, requisitionNumber: number, colour?: string | null, theirReference?: string | null, comment?: string | null, otherPartyName: string, otherPartyId: string, maxMonthsOfStock: number, minMonthsOfStock: number, approvalStatus: Types.RequisitionNodeApprovalStatus, programName?: string | null, orderType?: string | null, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, shipments: { __typename: 'InvoiceConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceNode', id: string, invoiceNumber: number, createdDatetime: string, user?: { __typename: 'UserNode', username: string } | null }> }, linesRemainingToSupply: { __typename: 'RequisitionLineConnector', totalCount: number }, lines: { __typename: 'RequisitionLineConnector', totalCount: number, nodes: Array<{ __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number } } | null }> }, otherParty: { __typename: 'NameNode', id: string, code: string, isCustomer: boolean, isSupplier: boolean, isOnHold: boolean, name: string, store?: { __typename: 'StoreNode', id: string, code: string } | null }, period?: { __typename: 'PeriodNode', name: string, startDate: string, endDate: string } | null, linkedRequisition?: { __typename: 'RequisitionNode', id: string } | null } }; +export type ResponseByNumberQuery = { __typename: 'Queries', requisitionByNumber: { __typename: 'RecordNotFound' } | { __typename: 'RequisitionNode', id: string, type: Types.RequisitionNodeType, status: Types.RequisitionNodeStatus, createdDatetime: string, sentDatetime?: string | null, finalisedDatetime?: string | null, requisitionNumber: number, colour?: string | null, theirReference?: string | null, comment?: string | null, otherPartyName: string, otherPartyId: string, maxMonthsOfStock: number, minMonthsOfStock: number, approvalStatus: Types.RequisitionNodeApprovalStatus, programName?: string | null, orderType?: string | null, user?: { __typename: 'UserNode', username: string, email?: string | null } | null, shipments: { __typename: 'InvoiceConnector', totalCount: number, nodes: Array<{ __typename: 'InvoiceNode', id: string, invoiceNumber: number, createdDatetime: string, user?: { __typename: 'UserNode', username: string } | null }> }, linesRemainingToSupply: { __typename: 'RequisitionLineConnector', totalCount: number }, lines: { __typename: 'RequisitionLineConnector', totalCount: number, nodes: Array<{ __typename: 'RequisitionLineNode', id: string, itemId: string, requestedQuantity: number, supplyQuantity: number, remainingQuantityToSupply: number, alreadyIssued: number, comment?: string | null, initialStockOnHandUnits: number, incomingUnits: number, outgoingUnits: number, lossInUnits: number, additionInUnits: number, expiringUnits: number, daysOutOfStock: number, optionId?: string | null, averageMonthlyConsumption: number, suggestedQuantity: number, availableStockOnHand: number, approvedQuantity: number, approvalComment?: string | null, itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, availableMonthsOfStockOnHand?: number | null, averageMonthlyConsumption: number }, item: { __typename: 'ItemNode', id: string, name: string, code: string, unitName?: string | null }, linkedRequisitionLine?: { __typename: 'RequisitionLineNode', itemStats: { __typename: 'ItemStatsNode', availableStockOnHand: number, averageMonthlyConsumption: number, availableMonthsOfStockOnHand?: number | null } } | null, reason?: { __typename: 'ReasonOptionNode', id: string, reason: string } | null }> }, otherParty: { __typename: 'NameNode', id: string, code: string, isCustomer: boolean, isSupplier: boolean, isOnHold: boolean, name: string, store?: { __typename: 'StoreNode', id: string, code: string } | null }, period?: { __typename: 'PeriodNode', name: string, startDate: string, endDate: string } | null, linkedRequisition?: { __typename: 'RequisitionNode', id: string } | null } }; export type ResponseRowFragment = { __typename: 'RequisitionNode', colour?: string | null, comment?: string | null, createdDatetime: string, finalisedDatetime?: string | null, id: string, otherPartyName: string, requisitionNumber: number, sentDatetime?: string | null, status: Types.RequisitionNodeStatus, theirReference?: string | null, type: Types.RequisitionNodeType, otherPartyId: string, approvalStatus: Types.RequisitionNodeApprovalStatus, programName?: string | null, orderType?: string | null, period?: { __typename: 'PeriodNode', name: string, startDate: string, endDate: string } | null, shipments: { __typename: 'InvoiceConnector', totalCount: number } }; @@ -110,6 +110,17 @@ export const ResponseLineFragmentDoc = gql` remainingQuantityToSupply alreadyIssued comment + initialStockOnHandUnits + incomingUnits + outgoingUnits + lossInUnits + additionInUnits + expiringUnits + daysOutOfStock + optionId + averageMonthlyConsumption + suggestedQuantity + availableStockOnHand itemStats { __typename availableStockOnHand @@ -127,8 +138,14 @@ export const ResponseLineFragmentDoc = gql` linkedRequisitionLine { itemStats { availableStockOnHand + averageMonthlyConsumption + availableMonthsOfStockOnHand } } + reason { + id + reason + } } `; export const ResponseFragmentDoc = gql` diff --git a/client/packages/requisitions/src/ResponseRequisition/api/operations.graphql b/client/packages/requisitions/src/ResponseRequisition/api/operations.graphql index 1d1924ae18..68de156fb3 100644 --- a/client/packages/requisitions/src/ResponseRequisition/api/operations.graphql +++ b/client/packages/requisitions/src/ResponseRequisition/api/operations.graphql @@ -18,6 +18,17 @@ fragment ResponseLine on RequisitionLineNode { remainingQuantityToSupply alreadyIssued comment + initialStockOnHandUnits + incomingUnits + outgoingUnits + lossInUnits + additionInUnits + expiringUnits + daysOutOfStock + optionId + averageMonthlyConsumption + suggestedQuantity + availableStockOnHand itemStats { __typename @@ -36,8 +47,15 @@ fragment ResponseLine on RequisitionLineNode { linkedRequisitionLine { itemStats { availableStockOnHand + averageMonthlyConsumption + availableMonthsOfStockOnHand } } + + reason { + id + reason + } } fragment Response on RequisitionNode { From 782602c6ad95d9b1029cc6f21c388c56a93138cb Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:09:50 +1300 Subject: [PATCH 09/16] Display new requisition columns in response requisition --- .../common/src/intl/locales/en/common.json | 13 +- .../ResponseRequisition/DetailView/columns.ts | 186 +++++++++++++++++- 2 files changed, 192 insertions(+), 7 deletions(-) diff --git a/client/packages/common/src/intl/locales/en/common.json b/client/packages/common/src/intl/locales/en/common.json index 80b1fd33e5..70a45bd6b1 100644 --- a/client/packages/common/src/intl/locales/en/common.json +++ b/client/packages/common/src/intl/locales/en/common.json @@ -154,6 +154,8 @@ "description.fc-line-total": "Foreign currency line total", "description.fc-sell-price": "Foreign currency sell price per pack", "description.forecast-quantity": "Forecast Quantity to Reach Target", + "description.initial-stock-on-hand": "Stock on hand on the first day of the program period", + "description.available-stock": "The customer's initial stock on hand + incoming stock + inventory adjustments - outgoing stock", "description.invoice-number": "Shipment number", "description.last-reading-datetime": "Date and time of the last reading", "description.max-min-temperature": "Maximum or minimum temperature reading", @@ -231,9 +233,9 @@ "error.failed-to-create-return": "Failed to create return!", "error.failed-to-generate-excel": "Failed to generate Excel", "error.failed-to-generate-report": "Failed to generate report", + "error.failed-to-save-item-variant": "Failed to save item variant", "error.failed-to-save-service-charges": "Failed to save service charges", "error.failed-to-save-vaccination": "Failed to save vaccination!", - "error.failed-to-save-item-variant": "Failed to save item variant", "error.failed-to-save-vaccine-course": "Failed to save vaccine course", "error.fetch-notifications": "Unable to display cold chain notifications", "error.field-must-be-specified": "{{field}} must be specified", @@ -503,6 +505,7 @@ "label.add-new-vaccine-course": "Add vaccine course", "label.add-variant": "Add variant", "label.additional-info": "Additional Info", + "label.additions": "Additions", "label.address": "Address", "label.adjust-by": "by", "label.adjusted": "Adjusted", @@ -531,6 +534,7 @@ "label.asset-properties": "Asset Properties", "label.atc-category": "ATC category", "label.auth-status": "Approval Status", + "label.available": "Available", "label.available-batches": "Available batches", "label.available-packs": "Available (packs)", "label.available-quantity": "Available quantity: {{number}} units", @@ -570,7 +574,6 @@ "label.cold-consecutive": "Cold Consecutive", "label.cold-cumulative": "Cold Cumulative", "label.cold-storage-location": "Cold storage location", - "label.storage-type": "Storage type", "label.collapse": "Collapse", "label.collapse-all": "Collapse all", "label.color": "Colour", @@ -616,6 +619,7 @@ "label.date-of-birth": "Date of Birth", "label.date-time": "Date time", "label.day": "day", + "label.days-out-of-stock": "Days out of stock", "label.ddd": "Defined Daily Dose", "label.deceased": "Deceased", "label.decrease-qty": "Decrease quantity", @@ -718,8 +722,10 @@ "label.inbound-not-delivered": "Inbound shipments not delivered", "label.inbound-shipment": "Inbound shipment", "label.inbound-shipment-cant-delete-reserved-line": "Batch {{batch}} (item code {{itemCode}}) is already reserved/issued", + "label.incoming": "Incoming", "label.incoming-stock": "Stock arriving", "label.increase-qty": "Increase quantity", + "label.initial-stock-on-hand": "Initial SOH", "label.initialise-store-properties": "Initialise store properties for GAPS", "label.initialised": "Initialised", "label.installation-date": "Installation date", @@ -835,6 +841,7 @@ "label.out-of-stock": "Out of stock", "label.outbound-shipment": "Outbound shipment", "label.outer-pack-size": "Outer pack size", + "label.outgoing": "Outgoing", "label.pack": "Pack", "label.pack-cost-price": "Pack cost price", "label.pack-quantity": "Pack Qty", @@ -934,6 +941,7 @@ "label.shipment-created": "Shipment created", "label.shipments": "Shipments", "label.shipped": "Shipped", + "label.short-expiry": "Short Expiry", "label.showing": "Showing", "label.site": "Site:", "label.snapshot-num-of-packs": "Snapshot Packs", @@ -952,6 +960,7 @@ "label.stocktake-comment": "Comment", "label.stocktake-date": "Stocktake Date", "label.stocktake-frequency": "Stocktake frequency", + "label.storage-type": "Storage type", "label.store": "Store", "label.strength": "Strength", "label.sub-catalogue": "Sub catalogue", diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts index 1466c7000c..35b11e7cf7 100644 --- a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts +++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts @@ -21,6 +21,10 @@ export const useResponseColumns = () => { queryParams: { sortBy }, } = useUrlQueryParams({ initialSort: { key: 'itemName', dir: 'asc' } }); const { isRemoteAuthorisation } = useResponse.utils.isRemoteAuthorisation(); + const { programName, linkedRequisition } = useResponse.document.fields([ + 'programName', + 'linkedRequisition', + ]); const isPackVariantsEnabled = useIsPackVariantsEnabled(); const columnDefinitions: ColumnDescription[] = [ @@ -69,18 +73,182 @@ export const useResponseColumns = () => { }), }, ], - { + ]; + + if (!programName) { + columnDefinitions.push({ key: 'customerStockOnHand', label: 'label.customer-soh', description: 'description.customer-soh', width: 100, align: ColumnAlign.Right, getSortValue: rowData => - rowData.linkedRequisitionLine?.itemStats?.availableStockOnHand ?? '', + linkedRequisition + ? (rowData.linkedRequisitionLine?.itemStats?.availableStockOnHand ?? + 0) + : rowData.availableStockOnHand, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => + linkedRequisition + ? (row.linkedRequisitionLine?.itemStats?.availableStockOnHand ?? 0) + : row.availableStockOnHand, + }), + }); + } + columnDefinitions.push( + // TODO: Global pref to show/hide the next columns + { + key: 'initialStockOnHand', + label: 'label.initial-stock-on-hand', + width: 100, + align: ColumnAlign.Right, + sortable: false, + description: 'description.initial-stock-on-hand', + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.initialStockOnHandUnits, + }), + }, + { + key: 'incomingStock', + label: 'label.incoming', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.incomingUnits, + }), + }, + { + key: 'outgoingUnits', + label: 'label.outgoing', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.outgoingUnits, + }), + }, + { + key: 'losses', + label: 'label.losses', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.lossInUnits, + }), + }, + { + key: 'additions', + label: 'label.additions', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.additionInUnits, + }), + }, + { + key: 'availableUnits', + label: 'label.available', + width: 100, + align: ColumnAlign.Right, + sortable: false, + description: 'description.available-stock', + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => + (linkedRequisition + ? row.itemStats.availableStockOnHand + : row.availableStockOnHand) + + row.incomingUnits + + row.additionInUnits - + row.lossInUnits - + row.outgoingUnits, + }), + }, + { + key: 'expiringUnits', + label: 'label.short-expiry', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.expiringUnits, + }), + }, + { + key: 'daysOutOfStock', + label: 'label.days-out-of-stock', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.daysOutOfStock, + }), + }, + { + key: 'amc', + label: 'label.amc', + width: 100, + align: ColumnAlign.Right, + sortable: false, Cell: PackVariantQuantityCell({ getItemId: row => row.itemId, getQuantity: row => - row?.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0, + linkedRequisition + ? (row.linkedRequisitionLine?.itemStats.averageMonthlyConsumption ?? + 0) + : row.averageMonthlyConsumption, + }), + }, + { + key: 'mos', + label: 'label.months-of-stock', + width: 100, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => + (() => { + const availableStock = linkedRequisition + ? (row.linkedRequisitionLine?.itemStats?.availableStockOnHand ?? + 0) + : row.availableStockOnHand + + row.incomingUnits + + row.additionInUnits - + row.lossInUnits - + row.outgoingUnits; + + const averageMonthlyConsumption = linkedRequisition + ? (row.linkedRequisitionLine?.itemStats + .averageMonthlyConsumption ?? 0) + : row.averageMonthlyConsumption; + + return averageMonthlyConsumption !== 0 + ? availableStock / averageMonthlyConsumption + : 0; + })(), + }), + }, + { + key: 'suggestedQuantity', + label: 'label.suggested-quantity', + width: 150, + align: ColumnAlign.Right, + sortable: false, + Cell: PackVariantQuantityCell({ + getItemId: row => row.itemId, + getQuantity: row => row.suggestedQuantity, }), }, [ @@ -93,8 +261,8 @@ export const useResponseColumns = () => { }), width: 150, }, - ], - ]; + ] + ); if (isRemoteAuthorisation) { columnDefinitions.push({ @@ -124,6 +292,14 @@ export const useResponseColumns = () => { }, ]); + // TODO: Global pref to show/hide column + columnDefinitions.push({ + key: 'reason', + label: 'label.reason', + sortable: false, + accessor: ({ rowData }) => rowData.reason?.reason, + }); + columnDefinitions.push({ label: 'label.already-issued', description: 'description.already-issued', From 42081878a6b4bfbc962af72346e765d82f9e295d Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:25:44 +1300 Subject: [PATCH 10/16] Remove console log --- .../src/ResponseRequisition/DetailView/columns.ts | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts index b91de304a6..fe33363955 100644 --- a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts +++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts @@ -137,19 +137,14 @@ export const useResponseColumns = () => { sortable: false, description: 'description.available-stock', Cell: PackQuantityCell, - accessor: ({ rowData }) => { - const availableStock = !!linkedRequisition + accessor: ({ rowData }) => + !!linkedRequisition ? (rowData.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0) : rowData.availableStockOnHand + rowData.incomingUnits + rowData.additionInUnits - rowData.lossInUnits - - rowData.outgoingUnits; - - console.log('Available stock: ', rowData.incomingUnits); - - return availableStock; - }, + rowData.outgoingUnits, }, { key: 'expiringUnits', From 316a92c32d9c868035cc0f052a2becc19725e0d3 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Wed, 30 Oct 2024 12:38:37 +1300 Subject: [PATCH 11/16] Refactor calculation to be easier to read --- .../ResponseRequisition/DetailView/columns.ts | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts index fe33363955..4e17c5fa38 100644 --- a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts +++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts @@ -137,14 +137,16 @@ export const useResponseColumns = () => { sortable: false, description: 'description.available-stock', Cell: PackQuantityCell, - accessor: ({ rowData }) => - !!linkedRequisition + accessor: ({ rowData }) => { + const stockOnHand = linkedRequisition ? (rowData.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0) - : rowData.availableStockOnHand + - rowData.incomingUnits + - rowData.additionInUnits - - rowData.lossInUnits - - rowData.outgoingUnits, + : rowData.availableStockOnHand; + + const incomingStock = rowData.incomingUnits + rowData.additionInUnits; + const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits; + + return stockOnHand + incomingStock - outgoingStock; + }, }, { key: 'expiringUnits', @@ -185,13 +187,13 @@ export const useResponseColumns = () => { sortable: false, Cell: PackQuantityCell, accessor: ({ rowData }) => { - const availableStock = linkedRequisition + const stockOnHand = linkedRequisition ? (rowData.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0) - : rowData.availableStockOnHand + - rowData.incomingUnits + - rowData.additionInUnits - - rowData.lossInUnits - - rowData.outgoingUnits; + : rowData.availableStockOnHand; + const incomingStock = rowData.incomingUnits + rowData.additionInUnits; + const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits; + + const available = stockOnHand + incomingStock - outgoingStock; const averageMonthlyConsumption = linkedRequisition ? (rowData.linkedRequisitionLine?.itemStats @@ -199,7 +201,7 @@ export const useResponseColumns = () => { : rowData.averageMonthlyConsumption; return averageMonthlyConsumption !== 0 - ? availableStock / averageMonthlyConsumption + ? available / averageMonthlyConsumption : 0; }, }, From 1be65da8d147c31cc254c92a6b2237856d0ae17e Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Thu, 31 Oct 2024 11:26:38 +1300 Subject: [PATCH 12/16] Rename function --- server/service/src/item/item.rs | 2 +- .../response_requisition_line/insert/validate.rs | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/server/service/src/item/item.rs b/server/service/src/item/item.rs index d79bbfb8d2..d390ef93d8 100644 --- a/server/service/src/item/item.rs +++ b/server/service/src/item/item.rs @@ -37,7 +37,7 @@ pub fn check_item_exists( Ok(count > 0) } -pub fn check_item_exists_return_item( +pub fn get_item( connection: &StorageConnection, store_id: String, item_id: &str, diff --git a/server/service/src/requisition_line/response_requisition_line/insert/validate.rs b/server/service/src/requisition_line/response_requisition_line/insert/validate.rs index 6249f57ba8..52807669cd 100644 --- a/server/service/src/requisition_line/response_requisition_line/insert/validate.rs +++ b/server/service/src/requisition_line/response_requisition_line/insert/validate.rs @@ -1,7 +1,7 @@ use repository::{ItemRow, RequisitionRow, RequisitionStatus, RequisitionType, StorageConnection}; use crate::{ - item::check_item_exists_return_item, + item::get_item, requisition::common::check_requisition_row_exists, requisition_line::common::{check_item_exists_in_requisition, check_requisition_line_exists}, }; @@ -42,7 +42,7 @@ pub fn validate( return Err(OutError::ItemAlreadyExistInRequisition); } - let item = check_item_exists_return_item(connection, store_id.to_string(), &input.item_id)? + let item = get_item(connection, store_id.to_string(), &input.item_id)? .ok_or(OutError::ItemDoesNotExist)?; Ok((requisition_row, item.item_row)) From 1e771155893b23042553eff7b68afdec3b29c989 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Thu, 31 Oct 2024 11:59:53 +1300 Subject: [PATCH 13/16] Use requisition line stats instead of itemStats --- .../ResponseRequisition/DetailView/columns.ts | 35 ++++--------------- 1 file changed, 7 insertions(+), 28 deletions(-) diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts index 4e17c5fa38..5555f08af0 100644 --- a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts +++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts @@ -17,10 +17,7 @@ export const useResponseColumns = () => { queryParams: { sortBy }, } = useUrlQueryParams({ initialSort: { key: 'itemName', dir: 'asc' } }); const { isRemoteAuthorisation } = useResponse.utils.isRemoteAuthorisation(); - const { programName, linkedRequisition } = useResponse.document.fields([ - 'programName', - 'linkedRequisition', - ]); + const { programName } = useResponse.document.fields(['programName']); const columnDefinitions: ColumnDescription[] = [ getCommentPopoverColumn(), @@ -70,15 +67,8 @@ export const useResponseColumns = () => { width: 100, align: ColumnAlign.Right, Cell: PackQuantityCell, - getSortValue: rowData => - linkedRequisition - ? (rowData.linkedRequisitionLine?.itemStats?.availableStockOnHand ?? - 0) - : rowData.availableStockOnHand, - accessor: ({ rowData }) => - linkedRequisition - ? rowData.linkedRequisitionLine?.itemStats?.availableStockOnHand - : rowData.availableStockOnHand, + getSortValue: rowData => rowData.availableStockOnHand, + accessor: ({ rowData }) => rowData.availableStockOnHand, }); } columnDefinitions.push( @@ -138,9 +128,7 @@ export const useResponseColumns = () => { description: 'description.available-stock', Cell: PackQuantityCell, accessor: ({ rowData }) => { - const stockOnHand = linkedRequisition - ? (rowData.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0) - : rowData.availableStockOnHand; + const stockOnHand = rowData.availableStockOnHand; const incomingStock = rowData.incomingUnits + rowData.additionInUnits; const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits; @@ -173,11 +161,7 @@ export const useResponseColumns = () => { align: ColumnAlign.Right, sortable: false, Cell: PackQuantityCell, - accessor: ({ rowData }) => - linkedRequisition - ? (rowData.linkedRequisitionLine?.itemStats - .averageMonthlyConsumption ?? 0) - : rowData.averageMonthlyConsumption, + accessor: ({ rowData }) => rowData.averageMonthlyConsumption, }, { key: 'mos', @@ -187,18 +171,13 @@ export const useResponseColumns = () => { sortable: false, Cell: PackQuantityCell, accessor: ({ rowData }) => { - const stockOnHand = linkedRequisition - ? (rowData.linkedRequisitionLine?.itemStats.availableStockOnHand ?? 0) - : rowData.availableStockOnHand; + const stockOnHand = rowData.availableStockOnHand; const incomingStock = rowData.incomingUnits + rowData.additionInUnits; const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits; const available = stockOnHand + incomingStock - outgoingStock; - const averageMonthlyConsumption = linkedRequisition - ? (rowData.linkedRequisitionLine?.itemStats - .averageMonthlyConsumption ?? 0) - : rowData.averageMonthlyConsumption; + const averageMonthlyConsumption = rowData.averageMonthlyConsumption; return averageMonthlyConsumption !== 0 ? available / averageMonthlyConsumption From b21f7cc268bf9f9af5279be5b76b2c4a25b13c22 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Thu, 31 Oct 2024 12:06:25 +1300 Subject: [PATCH 14/16] Opps --- client/packages/common/src/intl/locales/en/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/packages/common/src/intl/locales/en/common.json b/client/packages/common/src/intl/locales/en/common.json index dbf467b56c..53ee855321 100644 --- a/client/packages/common/src/intl/locales/en/common.json +++ b/client/packages/common/src/intl/locales/en/common.json @@ -155,7 +155,7 @@ "description.fc-sell-price": "Foreign currency sell price per pack", "description.forecast-quantity": "Forecast Quantity to Reach Target", "description.initial-stock-on-hand": "Stock on hand on the first day of the program period", - "description.available-stock": "The customer's initial stock on hand + incoming stock + inventory adjustments - outgoing stock", + "description.available-stock": "The customer's initial stock on hand + incoming stock + inventory adjustments - losses - outgoing stock", "description.invoice-number": "Shipment number", "description.last-reading-datetime": "Date and time of the last reading", "description.max-min-temperature": "Maximum or minimum temperature reading", From f04d14f14bffe5ab9359d242e3afcf032344ad13 Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Thu, 31 Oct 2024 14:42:30 +1300 Subject: [PATCH 15/16] Rephrase --- client/packages/common/src/intl/locales/en/common.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/packages/common/src/intl/locales/en/common.json b/client/packages/common/src/intl/locales/en/common.json index 53ee855321..d1fc2dcb9b 100644 --- a/client/packages/common/src/intl/locales/en/common.json +++ b/client/packages/common/src/intl/locales/en/common.json @@ -155,7 +155,7 @@ "description.fc-sell-price": "Foreign currency sell price per pack", "description.forecast-quantity": "Forecast Quantity to Reach Target", "description.initial-stock-on-hand": "Stock on hand on the first day of the program period", - "description.available-stock": "The customer's initial stock on hand + incoming stock + inventory adjustments - losses - outgoing stock", + "description.available-stock": "The customer's initial stock on hand + incoming stock +/- inventory adjustments - outgoing stock", "description.invoice-number": "Shipment number", "description.last-reading-datetime": "Date and time of the last reading", "description.max-min-temperature": "Maximum or minimum temperature reading", From 84b2eed66c05b5c4449b03627570b88a61cd0f5a Mon Sep 17 00:00:00 2001 From: roxy-dao Date: Mon, 4 Nov 2024 15:19:47 +1300 Subject: [PATCH 16/16] Change available SOH -> initial --- .../src/ResponseRequisition/DetailView/columns.ts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts index 5555f08af0..4f279dadd0 100644 --- a/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts +++ b/client/packages/requisitions/src/ResponseRequisition/DetailView/columns.ts @@ -128,7 +128,7 @@ export const useResponseColumns = () => { description: 'description.available-stock', Cell: PackQuantityCell, accessor: ({ rowData }) => { - const stockOnHand = rowData.availableStockOnHand; + const stockOnHand = rowData.initialStockOnHandUnits; const incomingStock = rowData.incomingUnits + rowData.additionInUnits; const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits; @@ -171,7 +171,7 @@ export const useResponseColumns = () => { sortable: false, Cell: PackQuantityCell, accessor: ({ rowData }) => { - const stockOnHand = rowData.availableStockOnHand; + const stockOnHand = rowData.initialStockOnHandUnits; const incomingStock = rowData.incomingUnits + rowData.additionInUnits; const outgoingStock = rowData.lossInUnits + rowData.outgoingUnits;