add deep diff pd
This commit is contained in:
parent
64a7dae017
commit
6ccc6cb779
5 changed files with 67 additions and 53 deletions
|
|
@ -48,6 +48,7 @@ macro_rules! update_each_field {
|
|||
/// about its structure.
|
||||
/// * `MaterialCode`: MaterialCode is a vector (array) that contains instances of the MaterialCode
|
||||
/// struct.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
||||
pub struct Recipe {
|
||||
pub Timestamp: String,
|
||||
|
|
@ -91,6 +92,8 @@ impl Recipe {
|
|||
}
|
||||
}
|
||||
|
||||
/// Get undefined fields from the recipe. This may included newer fields.
|
||||
///
|
||||
pub fn get_additional_fields(&self) -> Option<Value> {
|
||||
if self.extra.is_empty() {
|
||||
return None;
|
||||
|
|
@ -115,12 +118,14 @@ impl Recipe {
|
|||
.find(|&r| r.productCode == product_code)
|
||||
}
|
||||
|
||||
/// Similar to `search_pd` but ignoring exacted matching.
|
||||
pub fn search_pd_by_no_country_code(&self, product_code: String) -> Option<&Recipe01> {
|
||||
self.Recipe01
|
||||
.iter()
|
||||
.find(|&r| r.productCode.contains(&product_code))
|
||||
}
|
||||
|
||||
/// Mulitple product code searching with parallel and no exact matching.
|
||||
pub fn search_multi_in_parallel(&self, pds: Vec<String>) -> Vec<Option<Recipe01>> {
|
||||
let mut found = Vec::new();
|
||||
|
||||
|
|
@ -136,6 +141,7 @@ impl Recipe {
|
|||
found
|
||||
}
|
||||
|
||||
/// Get position of product code in the recipe's `Recipe01`
|
||||
pub fn get_pd_index(&self, product_code: String) -> usize {
|
||||
self.Recipe01
|
||||
.iter()
|
||||
|
|
@ -143,26 +149,32 @@ impl Recipe {
|
|||
.unwrap()
|
||||
}
|
||||
|
||||
/// Search expected material setting if existed
|
||||
pub fn search_material_settings(&self, material_code: String) -> Option<&MaterialSetting> {
|
||||
self.MaterialSetting
|
||||
.iter()
|
||||
.find(|r| r.id.to_string() == material_code)
|
||||
}
|
||||
|
||||
/// Search expected topping list if existed
|
||||
pub fn search_topping_list(&self, id: String) -> Option<&ToppingList> {
|
||||
self.Topping.ToppingList.iter().find(|&r| r.id == id)
|
||||
}
|
||||
|
||||
/// Search expected topping group if existed
|
||||
pub fn search_topping_group(&self, id: String) -> Option<&ToppingGroup> {
|
||||
self.Topping.ToppingGroup.iter().find(|&r| r.groupID == id)
|
||||
}
|
||||
|
||||
/// Search expected material code if existed
|
||||
pub fn search_material_code(&self, material_code: String) -> Option<&MaterialCode> {
|
||||
self.MaterialCode
|
||||
.iter()
|
||||
.find(|&r| r.materialID == material_code)
|
||||
}
|
||||
|
||||
/// Check if expected product code is different in both recipes.
|
||||
/// This may return `false` if either one did not have this product code.
|
||||
pub fn diff_pd_between_recipes(&self, another_recipe: &Recipe, product_code: String) -> bool {
|
||||
let menu1 = Self::search_pd(self, product_code.clone());
|
||||
let menu2 = Self::search_pd(another_recipe, product_code.clone());
|
||||
|
|
@ -177,6 +189,7 @@ impl Recipe {
|
|||
menu1 == menu2
|
||||
}
|
||||
|
||||
/// Similar to `diff_pd_between_recipes` but will not check exacted matching.
|
||||
pub fn diff_pd_between_recipes_ignore_country(
|
||||
&self,
|
||||
another_recipe: &Recipe,
|
||||
|
|
@ -195,6 +208,35 @@ impl Recipe {
|
|||
menu1 == menu2
|
||||
}
|
||||
|
||||
pub fn deep_diff_pd_between_recipes(
|
||||
&self,
|
||||
another_recipe: &Recipe,
|
||||
product_code: String,
|
||||
) -> Vec<(String, bool)> {
|
||||
let mut result = Vec::new();
|
||||
|
||||
let self_recipe = Self::search_pd_by_no_country_code(self, product_code.clone());
|
||||
let another_recipe =
|
||||
Self::search_pd_by_no_country_code(another_recipe, product_code.clone());
|
||||
|
||||
if self_recipe.is_some() && another_recipe.is_some() {
|
||||
let sr = self_recipe.unwrap();
|
||||
let ar = another_recipe.unwrap();
|
||||
|
||||
let diff_field_list = sr.compare(ar);
|
||||
|
||||
for key in sr.to_map().keys() {
|
||||
if diff_field_list.contains(key) {
|
||||
result.push((key.to_string(), true));
|
||||
} else {
|
||||
result.push((key.to_string(), false));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
result
|
||||
}
|
||||
|
||||
pub fn diff_material_setting_between_recipes(
|
||||
&self,
|
||||
another_recipe: &Recipe,
|
||||
|
|
@ -522,6 +564,7 @@ impl Recipe {
|
|||
pub fn add_prefix_country_code(&mut self) {}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn StrShowTextErrorDefault() -> Option<Vec<Value>> {
|
||||
Some(vec![
|
||||
Value::String("เต่าบินเกิดเหตุขัดข้อง".into()),
|
||||
|
|
@ -569,6 +612,7 @@ impl PartialRecipe {
|
|||
/// temperature setting for a machine.
|
||||
/// * `temperatureMin`: The `temperatureMin` property is of type `Value`. It represents the minimum
|
||||
/// temperature setting for the machine.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct MachineSetting {
|
||||
pub Comment: Option<Vec<String>>,
|
||||
|
|
@ -659,26 +703,32 @@ impl CommonRecipeTrait for MachineSetting {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankString() -> Option<String> {
|
||||
Some("".to_string())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankBool() -> Option<bool> {
|
||||
Some(false)
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankVecString() -> Option<Vec<String>> {
|
||||
Some(vec![].into())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankVecRecipe() -> Option<Vec<Recipe01>> {
|
||||
Some(vec![].into())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankVecMenuTopping() -> Option<Vec<MenuToppingList>> {
|
||||
Some(vec![].into())
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankOtherStrShowTextError() -> Option<Vec<String>> {
|
||||
Some(vec![
|
||||
"".to_string(),
|
||||
|
|
@ -692,14 +742,17 @@ fn BlankOtherStrShowTextError() -> Option<Vec<String>> {
|
|||
])
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankValueString() -> Option<Value> {
|
||||
Some(Value::String("".into()))
|
||||
}
|
||||
|
||||
#[allow(non_snake_case, dead_code)]
|
||||
fn BlankValueArray() -> Option<Value> {
|
||||
Some(Value::Array(vec![].into()))
|
||||
}
|
||||
|
||||
#[allow(non_snake_case, dead_code)]
|
||||
fn BlankValueBool() -> Option<Value> {
|
||||
Some(Value::Bool(false.into()))
|
||||
}
|
||||
|
|
@ -754,6 +807,7 @@ fn BlankValueBool() -> Option<Value> {
|
|||
/// * `useGram`: A boolean value indicating whether the recipe uses grams for measurement or not.
|
||||
/// * `weight_float`: The `weight_float` property is of type `Value` and represents the weight of the
|
||||
/// recipe as a floating-point number.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct Recipe01 {
|
||||
#[serde(default = "BlankString")]
|
||||
|
|
@ -1371,6 +1425,7 @@ impl Recipe01 {
|
|||
/// water in the recipe.
|
||||
/// * `waterYield`: The `waterYield` property represents the amount of water produced or obtained from
|
||||
/// the recipe.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct RecipeList {
|
||||
pub MixOrder: Value,
|
||||
|
|
@ -1465,6 +1520,7 @@ impl RecipeList {
|
|||
/// maximum number of retries for a payment.
|
||||
/// * `RawMaterialUnit`: The `RawMaterialUnit` property is an optional string that represents the unit
|
||||
/// of measurement for the raw material.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct MaterialSetting {
|
||||
pub AlarmIDWhenOffline: Value,
|
||||
|
|
@ -1576,6 +1632,7 @@ impl MachineSetting {
|
|||
}
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankListGroupID() -> Option<Vec<Value>> {
|
||||
Some(vec![
|
||||
Value::String("0".into()),
|
||||
|
|
@ -1585,6 +1642,7 @@ fn BlankListGroupID() -> Option<Vec<Value>> {
|
|||
])
|
||||
}
|
||||
|
||||
#[allow(non_snake_case)]
|
||||
fn BlankGroupID() -> Option<Value> {
|
||||
Some(Value::String("0".into()))
|
||||
}
|
||||
|
|
@ -1600,6 +1658,7 @@ fn BlankGroupID() -> Option<Value> {
|
|||
/// which the menu topping list belongs.
|
||||
/// * `isUse`: The `isUse` property is a boolean value that indicates whether the menu topping list is
|
||||
/// being used or not.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct MenuToppingList {
|
||||
#[serde(default = "BlankListGroupID")]
|
||||
|
|
@ -1620,6 +1679,7 @@ pub struct MenuToppingList {
|
|||
/// struct. Each ToppingGroup struct represents a group of toppings.
|
||||
/// * `ToppingList`: The `ToppingList` property is a vector (dynamic array) that contains elements of
|
||||
/// type `ToppingList`.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct Topping {
|
||||
pub ToppingGroup: Vec<ToppingGroup>,
|
||||
|
|
@ -1643,6 +1703,7 @@ pub struct Topping {
|
|||
/// * `name`: The `name` property is a string that represents the name of the topping group.
|
||||
/// * `otherName`: The `otherName` property is a string that represents an alternative name for the
|
||||
/// `ToppingGroup`. It can be used to provide additional information or a different name for the group.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct ToppingGroup {
|
||||
pub groupID: Value,
|
||||
|
|
@ -1703,6 +1764,7 @@ impl ToppingGroup {
|
|||
/// * `useGram`: A boolean value indicating whether the topping uses grams for measurement or not.
|
||||
/// * `weight_float`: The `weight_float` property is of type `Value` and represents the weight of the
|
||||
/// topping in float format.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct ToppingList {
|
||||
pub ExtendID: Value,
|
||||
|
|
@ -1754,6 +1816,7 @@ impl ToppingList {
|
|||
/// * `materialCode`: The `materialCode` property is an optional field that represents the code
|
||||
/// associated with a material. It is of type `Option<String>`, which means it can either be
|
||||
/// `Some(String)` if a value is present, or `None` if no value is provided.
|
||||
#[allow(non_snake_case)]
|
||||
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Clone)]
|
||||
pub struct MaterialCode {
|
||||
#[serde(default = "BlankString")]
|
||||
|
|
|
|||
|
|
@ -5,7 +5,7 @@ use std::collections::HashMap;
|
|||
use crate::models::recipe::*;
|
||||
use crate::recipe_functions::common::*;
|
||||
|
||||
/// Version 2 of `models::Recipe`
|
||||
/// Version 2 of `models::Recipe`, WIP
|
||||
///
|
||||
#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
|
||||
pub struct VersionRecipe {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue