From 7cdbca220ae10e37ee3cba04e0fb51bd0ee4c904 Mon Sep 17 00:00:00 2001 From: Ryan Ruckley Date: Wed, 13 Dec 2023 16:33:44 +1100 Subject: [PATCH 1/2] Add Price,QuotePrice to Quote --- examples/create_quote.rs | 14 ++++- src/tmf648/mod.rs | 1 + src/tmf648/quote.rs | 10 ++++ src/tmf648/quote_item.rs | 11 ++++ src/tmf648/quote_price.rs | 112 ++++++++++++++++++++++++++++++++++++++ 5 files changed, 145 insertions(+), 3 deletions(-) create mode 100644 src/tmf648/quote_price.rs diff --git a/examples/create_quote.rs b/examples/create_quote.rs index f6c4ed02..7ffe3fe6 100644 --- a/examples/create_quote.rs +++ b/examples/create_quote.rs @@ -1,12 +1,20 @@ //! Create Quote Example -use tmflib::tmf648::{quote::Quote, quote_item::QuoteItem}; +use tmflib::tmf648::{quote::Quote, quote_item::QuoteItem, quote_price::{Price,QuotePrice}}; fn main() { // Create a quote - let item = QuoteItem::new(); + let mut item = QuoteItem::new(); + let price = Price::new_ex(100.0); + let quote_price = QuotePrice::new("Subscription").price(price).period("Monthly"); + item.price(quote_price); let mut quote = Quote::new(); let _result = quote.add_quote(item); - let _result = quote.with_external_id(String::from("ExternalId")); + let _result = quote.with_external_id(String::from("EXT123")); + + let total_price = Price::new_ex(3600.0); + + let quote_total_price = QuotePrice::new("Total Contract").price(total_price).period("Contract"); + quote.price(quote_total_price); dbg!("e); } \ No newline at end of file diff --git a/src/tmf648/mod.rs b/src/tmf648/mod.rs index 8dac3ee1..787bde95 100644 --- a/src/tmf648/mod.rs +++ b/src/tmf648/mod.rs @@ -18,3 +18,4 @@ const MOD_PATH: &str = "tmf648/v4"; pub mod quote; pub mod quote_item; +pub mod quote_price; diff --git a/src/tmf648/quote.rs b/src/tmf648/quote.rs index c3f74d10..95d6b808 100644 --- a/src/tmf648/quote.rs +++ b/src/tmf648/quote.rs @@ -3,6 +3,7 @@ use serde::{Deserialize, Serialize}; use super::quote_item::QuoteItem; use super::MOD_PATH; +use super::quote_price::QuotePrice; use crate::common::note::Note; use crate::{LIB_PATH, HasId, CreateTMF}; @@ -62,6 +63,9 @@ pub struct Quote { /// Requested Start Date #[serde(skip_serializing_if = "Option::is_none")] pub start_date: Option, + /// Total Quote Pricing + #[serde(skip_serializing_if = "Option::is_none")] + pub quote_total_price : Option>, } impl Quote { @@ -71,6 +75,7 @@ impl Quote { quote.version = Some(QUOTE_VERS.to_string()); quote.state = Some(QuoteStateType::Accepted); quote.quote_item = Some(vec![]); + quote.quote_total_price = Some(vec![]); quote } @@ -85,6 +90,11 @@ impl Quote { Ok(String::from("Quote Item Added")) } + /// Add a price entry to this quote + pub fn price(&mut self, price : QuotePrice) { + self.quote_total_price.as_mut().unwrap().push(price); + } + /// Get a description for this quote pub fn description(&self) -> String { match &self.description { diff --git a/src/tmf648/quote_item.rs b/src/tmf648/quote_item.rs index a56ca928..c06cc6e2 100644 --- a/src/tmf648/quote_item.rs +++ b/src/tmf648/quote_item.rs @@ -8,6 +8,8 @@ use crate::common::note::Note; use crate::common::related_party::RelatedParty; use crate::tmf620::product_specification::ProductSpecificationRef; +use super::quote_price::QuotePrice; + /// Status of product for Quote Item #[derive(Clone, Default, Debug, Deserialize, Serialize)] pub enum ProductStatusType { @@ -90,6 +92,9 @@ pub struct QuoteItem { /// Product #[serde(skip_serializing_if = "Option::is_none")] pub product : Option, + /// Quote Item Pricing + #[serde(skip_serializing_if = "Option::is_none")] + quote_item_price : Option>, } impl QuoteItem { @@ -99,7 +104,13 @@ impl QuoteItem { QuoteItem { id : Some(id), quantity : 1, + quote_item_price : Some(vec![]), ..Default::default() } } + + /// Add QuotePrice to this QuoteItem + pub fn price(&mut self, price : QuotePrice) { + self.quote_item_price.as_mut().unwrap().push(price); + } } diff --git a/src/tmf648/quote_price.rs b/src/tmf648/quote_price.rs new file mode 100644 index 00000000..2c5de3cc --- /dev/null +++ b/src/tmf648/quote_price.rs @@ -0,0 +1,112 @@ +//! Quote Price Struct +//! + +use serde::{Deserialize,Serialize}; + +use crate::tmf620::product_offering_price::ProductOfferingPriceRef; + +/// Default tax rate for Australian market. +const AUS_TAX_RATE : f32 = 0.10; + +/// Price Structure +#[derive(Copy,Clone, Default, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct Price { + percentage : f32, + tax_rate: f32, + duty_free_amount : f32, + tax_included_amount : f32, +} + +impl Price { + /// Create a new Price object using a tax inclusive price + pub fn new_inc(inc_price : f32) -> Price { + let mut price = Price { + tax_rate : AUS_TAX_RATE, + ..Default::default() + }; + price.set_inc_price(inc_price); + price + } + + /// Create a new Price object using a tax exclusive price + pub fn new_ex(ex_price : f32) -> Price { + let mut price = Price { + tax_rate : AUS_TAX_RATE, + ..Default::default() + }; + price.set_ex_price(ex_price); + price + } + + /// Set the tax inclusive price + pub fn set_inc_price(&mut self, inc_price : f32) { + self.tax_included_amount = inc_price; + self.duty_free_amount = inc_price / self.tax_rate; + } + + /// Set the tax exclusive price + pub fn set_ex_price(&mut self, ex_price : f32) { + self.duty_free_amount = ex_price; + self.tax_included_amount = ex_price * (1.0+self.tax_rate); + } +} + +/// Quote Price Structure +#[derive(Clone, Default, Debug, Deserialize, Serialize)] +#[serde(rename_all = "camelCase")] +pub struct QuotePrice { + /// Description + #[serde(skip_serializing_if = "Option::is_none")] + pub description : Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// Name of price entry + pub name : Option, + #[serde(skip_serializing_if = "Option::is_none")] + price_type : Option, + #[serde(skip_serializing_if = "Option::is_none")] + recurring_charge_period: Option, + #[serde(skip_serializing_if = "Option::is_none")] + unit_of_measure : Option, + #[serde(skip_serializing_if = "Option::is_none")] + /// Pricing information + pub price : Option, + #[serde(skip_serializing_if = "Option::is_none")] + product_offering_price : Option, +} + +impl QuotePrice { + /// Create a new QuotePrice object with a given name + pub fn new(name : &str) -> QuotePrice { + QuotePrice { + name : Some(name.to_owned()), + ..Default::default() + } + } + /// Return the price inclusive of Tax + pub fn inc_tax(&self) -> f32 { + match self.price { + Some(p) => p.tax_included_amount, + None => 0.0, + } + } + /// Return the price exclusive of Tax + pub fn ex_tax(&self) -> f32 { + match self.price { + Some(p) => p.duty_free_amount, + None => 0.0, + } + } + + /// Add pricing to this QuotePrice + pub fn price(mut self, price : Price) -> QuotePrice { + self.price = Some(price); + self + } + + /// Set the period + pub fn period(mut self, period : &str) -> QuotePrice { + self.recurring_charge_period = Some(period.to_owned()); + self + } +} \ No newline at end of file From 61a0e2c4eb5342175d4f0324a8fd108787a1b76c Mon Sep 17 00:00:00 2001 From: Ryan Ruckley Date: Wed, 13 Dec 2023 16:42:10 +1100 Subject: [PATCH 2/2] Some comments. --- examples/create_quote.rs | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/examples/create_quote.rs b/examples/create_quote.rs index 7ffe3fe6..50089c83 100644 --- a/examples/create_quote.rs +++ b/examples/create_quote.rs @@ -2,18 +2,29 @@ use tmflib::tmf648::{quote::Quote, quote_item::QuoteItem, quote_price::{Price,QuotePrice}}; fn main() { - // Create a quote + // Create a quote using various components + + // First create a quote item let mut item = QuoteItem::new(); + // Create a price for this item let price = Price::new_ex(100.0); + // Add price to QuotePrice and set period let quote_price = QuotePrice::new("Subscription").price(price).period("Monthly"); + // add QuotePrice to item item.price(quote_price); + // Create the new Quote let mut quote = Quote::new(); + // Add the item to the quote let _result = quote.add_quote(item); + // Set the external Id let _result = quote.with_external_id(String::from("EXT123")); + // Create a total price for the quote let total_price = Price::new_ex(3600.0); + // Create QuotePrice object for the total price and set period let quote_total_price = QuotePrice::new("Total Contract").price(total_price).period("Contract"); + // Add QuotePrice to quote quote.price(quote_total_price); dbg!("e);