From 90c3cd2bd7cb160248148148b789a393503236c4 Mon Sep 17 00:00:00 2001 From: Pakin Date: Tue, 13 Jan 2026 14:01:54 +0700 Subject: [PATCH] feat: change prefix functions for new country - add shortcut for changing prefix in new country setup change: get latest version - remove restrains on country name checking Signed-off-by: Pakin --- src/recipe_functions/common.rs | 241 +++++++++++++++++++-------------- 1 file changed, 143 insertions(+), 98 deletions(-) diff --git a/src/recipe_functions/common.rs b/src/recipe_functions/common.rs index d8c8d8d..0e2279e 100644 --- a/src/recipe_functions/common.rs +++ b/src/recipe_functions/common.rs @@ -1,10 +1,12 @@ use rayon::iter::{IntoParallelRefMutIterator, ParallelIterator}; use serde_json::Value; -use crate::models::{self, recipe::Recipe01}; +use crate::models::{self, recipe::{MaterialCode, MaterialSetting, Recipe, Recipe01, ToppingList}}; use std::collections::HashMap; use std::{fs::File, io::Read}; +pub const MATERIAL_INTER_GUARD: usize = 300000; + pub trait EnumAsValue { fn name(&self) -> String; fn value(&self) -> T; @@ -126,107 +128,147 @@ pub fn check_allowed_change_mat_prefix(mat_id: Value) -> bool { } pub fn change_prefix_by_country( - country: &str, - mut recipes: Vec>, + recipes: Vec>, + cprefix: Option<&str> ) -> Vec { let mut result = Vec::new(); // get prefix first - let prefix = get_pd_prefix(country); - let mat_prefix = get_mat_prefix(country); + let prefix = cprefix.unwrap_or("").to_string(); - // run - let updated = recipes - .par_iter_mut() - .update(|x| { - if let Some(x) = x { - // change productCode - let mut new_product_code = x.productCode.clone(); - - new_product_code = - format!("{}-{}", prefix, new_product_code.split_once('-').unwrap().1); - x.productCode = new_product_code; - // run through recipes - let mut new_recipes_format = Vec::new(); - for ele in x.clone().recipes { - let mut eled = ele.clone(); - if check_allowed_change_mat_prefix(eled.clone().materialPathId) { - let curr_id = eled.clone().materialPathId.as_i64().unwrap_or(0); - - let new_f = if curr_id > 300000 { - // is from inter - - // TODO: reset first - let back_to_default_id = curr_id.to_string()[2..] - .parse::() - .expect("not a number"); - - format!("{}{}", mat_prefix, back_to_default_id) - } else { - // is from thai - format!("{}{}", mat_prefix, eled.clone().materialPathId) - }; - - eled.materialPathId = Value::Number(new_f.parse::().unwrap().into()); - } - new_recipes_format.push(eled); - } - x.recipes = new_recipes_format; - - if let Some(s) = x.clone().SubMenu { - // - let cls = s.clone(); - for mut sl in cls.clone() { - let mut new_sl_pd = sl.productCode.clone(); - new_sl_pd = format!("{}-{}", prefix, new_sl_pd.split_once('-').unwrap().1); - sl.productCode = new_sl_pd; - - let mut new_recipes_sub = Vec::new(); - for ele in sl.recipes { - let mut eled = ele.clone(); - if check_allowed_change_mat_prefix(eled.clone().materialPathId) { - let curr_id = eled.clone().materialPathId.as_i64().unwrap_or(0); - - let new_f = if curr_id > 300000 { - // is from inter - - // TODO: reset first - let back_to_default_id = curr_id.to_string()[2..] - .parse::() - .expect("not a number"); - - format!("{}{}", mat_prefix, back_to_default_id) - } else { - // is from thai - format!("{}{}", mat_prefix, eled.clone().materialPathId) - }; - eled.materialPathId = - Value::Number(new_f.parse::().unwrap().into()); - } - new_recipes_sub.push(eled); - } - sl.recipes = new_recipes_sub; - } - x.SubMenu = Some(cls.clone()); - } - } - }) - .filter(|x| x.is_some()) - .map(|x| x.clone().unwrap()) - .collect_vec_list(); - - // check by update - for x in updated.iter() { - result.extend_from_slice(x); + for rpl in recipes.iter() { + if let Some(rp) = rpl.clone() { + result.push(modify_prefix_recipe(rp.clone(), prefix.clone())); + } } result } +pub fn change_prefix_material_settings( + mut mat_set: Vec, + cprefix: String +) -> Vec { + let mut result = Vec::new(); + + for ms in mat_set.iter_mut() { + if let Some(mat_num) = ms.id.as_number() && + let Some(mat_id) = mat_num.as_i64() { + ms.id = assign_new_prefix_mat_id_by_case(mat_id, cprefix.clone()); + } + result.push(ms.clone()); + } + + result +} + +pub fn change_prefix_topping_list( + mut topp_list: Vec, + cprefix: String +) -> Vec { + let mut result = Vec::new(); + + for tpl in topp_list.iter_mut() { + for rpl in tpl.recipes.iter_mut() { + if let Some(mat_num) = rpl.materialPathId.as_number() && + let Some(mat_id) = mat_num.as_i64() { + rpl.materialPathId = assign_new_prefix_mat_id_by_case(mat_id, cprefix.clone()); + } + } + + result.push(tpl.clone()); + } + + result +} + +pub fn change_prefix_material_code( + mut mat_codes: Vec, + cprefix: String +) -> Vec{ + let mut result = Vec::new(); + + for mc in mat_codes.iter_mut() { + if let Some(mat_num) = mc.materialID.as_number() && + let Some(mat_id) = mat_num.as_i64() { + mc.materialID = assign_new_prefix_mat_id_by_case(mat_id, cprefix.clone()); + } + result.push(mc.clone()); + } + + result +} + +pub fn run_process_change_prefix(mut recipe: Recipe, prefix: String){ + recipe.Recipe01 = change_prefix_by_country(recipe.clone().Recipe01.clone().iter().map(|r| Some(r.clone())).collect(), Some(&prefix.clone())); + recipe.MaterialSetting = change_prefix_material_settings(recipe.clone().MaterialSetting.clone(), prefix.clone()); + recipe.Topping.ToppingList = change_prefix_topping_list(recipe.clone().Topping.ToppingList.clone(), prefix.clone()); + recipe.MaterialCode = change_prefix_material_code(recipe.clone().MaterialCode.clone(), prefix.clone()); +} + +fn modify_prefix_recipe(mut recp: Recipe01, prefix: String) -> Recipe01 { + let mut product_code = recp.productCode.clone(); + if product_code.is_empty() || product_code.len() < 13 { + return recp; + } + + product_code = format!("{prefix}-{rest}", rest = product_code.split_once("-").unwrap().1); + recp.productCode = product_code; + + // edit recipe + let mut changed_recipes_list = Vec::new(); + for rpl in recp.recipes.iter_mut() { + if check_allowed_change_mat_prefix(rpl.materialPathId.clone()) { + if let Some(mat_num) = rpl.materialPathId.as_number() && + let Some(mat_id) = mat_num.as_i64() { + rpl.materialPathId = assign_new_prefix_mat_id_by_case(mat_id, prefix.clone()); + } + } + changed_recipes_list.push(rpl.clone()); + } + recp.recipes = changed_recipes_list; + let mut changed_sub_menus = Vec::new(); + if let Some(mut subs) = recp.SubMenu.clone() { + for s in subs.iter_mut() { + changed_sub_menus.push(modify_prefix_recipe(s.clone(), prefix.clone())); + } + } + + recp.SubMenu = if recp.SubMenu.is_some() { + Some(changed_sub_menus.clone()) + } else { + None + }; + + + recp +} + +fn assign_new_prefix_mat_id_by_case(id: i64, prefix: String) -> Value{ + if id > MATERIAL_INTER_GUARD as i64 { + let inverted_mat_id = id.to_string()[2..].parse::().expect("not a number"); + let new_mat_id = format!("{prefix}{inverted_mat_id}"); + return serde_json::json!(new_mat_id.parse::().unwrap()); + } else { + let new_mat_id = format!("{prefix}{id}"); + return serde_json::json!(new_mat_id.parse::().unwrap()); + } +} + +#[deprecated] +/// DON'T USE +/// +/// Pre-defined country short name pub fn valid_country_name() -> Vec<&'static str> { vec!["mys", "sgp", "aus", "tha", "hkg", "dubai", "uae"] } +/// Get latest version for each country (defined by having `version` file) +/// where `dir_path` is the root directory of recipe repo +/// +/// `FIXME`: does not support string version, i.e. dev version is 001 and the result is +/// expected in `usize` which gets `1` instead. +/// pub fn grep_latest_versions(dir_path: &str) -> Result, std::io::Error> { let mut vs = HashMap::new(); @@ -237,22 +279,25 @@ pub fn grep_latest_versions(dir_path: &str) -> Result, st for e in entries { let path = e.clone().to_str().unwrap().to_string(); - let mut cl_path = path.clone(); let path_split = path.split("/").collect::>(); let dir_name = path_split[path_split.len() - 1]; - if valid_country_name().contains(&dir_name) { - cl_path.push_str("/version"); + // do check if dir contains version file + if let Ok(dr) = std::fs::read_dir(path.clone()) { + dr.for_each(|d| { + if let Ok(dt) = d + && dt.file_name().to_str().unwrap_or("").to_string().eq("version") + && let Ok(mut file_res) = File::open(dt.path()) + { + let mut data = String::new(); + let _ = file_res.read_to_string(&mut data); - // read filename - let mut file = File::open(cl_path)?; - let mut data = String::new(); - file.read_to_string(&mut data).unwrap(); + // TODO: does not support string version, i.e. dev version is 001 + vs.insert(dir_name.to_string(), data.parse::().unwrap()); - vs.insert(dir_name.to_string(), data.parse::().unwrap()); + } + }); } - - // expect dir with country } Ok(vs)