diff --git a/backend/gateways/spacegate-plugins/src/extension.rs b/backend/gateways/spacegate-plugins/src/extension.rs index e66e8cc51..5ef33bd20 100644 --- a/backend/gateways/spacegate-plugins/src/extension.rs +++ b/backend/gateways/spacegate-plugins/src/extension.rs @@ -1,4 +1,3 @@ - pub mod audit_log_param; pub mod before_encrypt_body; pub mod cert_info; diff --git a/backend/gateways/spacegate-plugins/src/extension/audit_log_param.rs b/backend/gateways/spacegate-plugins/src/extension/audit_log_param.rs index f0b4becdb..5b6d3db97 100644 --- a/backend/gateways/spacegate-plugins/src/extension/audit_log_param.rs +++ b/backend/gateways/spacegate-plugins/src/extension/audit_log_param.rs @@ -80,7 +80,7 @@ pub struct LogParamContent { impl LogParamContent { pub fn send_audit_log(self, spi_app_id: &str, log_url: &str, tag: &str) { - send_audit_log(spi_app_id, log_url, tag, self,P::get_funs_inst_by_plugin_code()); + send_audit_log(spi_app_id, log_url, tag, self, P::get_funs_inst_by_plugin_code()); } } diff --git a/backend/gateways/spacegate-plugins/src/extension/notification.rs b/backend/gateways/spacegate-plugins/src/extension/notification.rs index 22e12d4cb..a1f5e5de9 100644 --- a/backend/gateways/spacegate-plugins/src/extension/notification.rs +++ b/backend/gateways/spacegate-plugins/src/extension/notification.rs @@ -42,7 +42,7 @@ impl NotificationContext { } // set the dedup key - if let Err(e) = conn.set_ex::<'_, _, _,Option>(&key, "1", cool_down).await { + if let Err(e) = conn.set_ex::<'_, _, _, Option>(&key, "1", cool_down).await { tracing::error!(error = ?e, "set dedup cache failed"); return; } @@ -50,12 +50,9 @@ impl NotificationContext { let funs = NotifyPlugin::get_funs_inst_by_plugin_code(); tracing::debug!(?req, "submit notify"); let response = match req { - ReachRequest::ByScene(req) => { - bios_sdk_invoke::clients::reach_client::ReachClient::send_message(&req.into(), &funs, &ctx).await - - } + ReachRequest::ByScene(req) => bios_sdk_invoke::clients::reach_client::ReachClient::send_message(&req.into(), &funs, &ctx).await, ReachRequest::ByTemplate { contact, template_id, replace } => { - bios_sdk_invoke::clients::reach_client::ReachClient::general_send(&contact, &template_id, &replace, &funs, &ctx).await + bios_sdk_invoke::clients::reach_client::ReachClient::general_send(&contact, &template_id, &replace, &funs, &ctx).await } }; if let Err(e) = response { diff --git a/backend/gateways/spacegate-plugins/src/lib.rs b/backend/gateways/spacegate-plugins/src/lib.rs index 67c6a51de..9ef2019fb 100644 --- a/backend/gateways/spacegate-plugins/src/lib.rs +++ b/backend/gateways/spacegate-plugins/src/lib.rs @@ -1,6 +1,6 @@ #![warn(clippy::unwrap_used)] -pub use crate::plugin::{anti_replay, anti_xss, audit_log, auth, ip_time, rewrite_ns_b_ip, content_filter}; +pub use crate::plugin::{anti_replay, anti_xss, audit_log, auth, content_filter, ip_time, rewrite_ns_b_ip}; mod consts; mod extension; diff --git a/backend/gateways/spacegate-plugins/src/plugin/content_filter.rs b/backend/gateways/spacegate-plugins/src/plugin/content_filter.rs index 942343188..875f67155 100644 --- a/backend/gateways/spacegate-plugins/src/plugin/content_filter.rs +++ b/backend/gateways/spacegate-plugins/src/plugin/content_filter.rs @@ -111,7 +111,9 @@ impl Plugin for ContentFilterPlugin { for f in &self.forbidden_pq_filter { if f.matches(pq.as_str().as_bytes()) { let mut response = SgResponse::with_code_empty(StatusCode::BAD_REQUEST); - response.extensions_mut().insert(ContentFilterForbiddenReport { forbidden_reason: format!("forbidden rule matched: {f}") }); + response.extensions_mut().insert(ContentFilterForbiddenReport { + forbidden_reason: format!("forbidden rule matched: {f}"), + }); return Ok(response); } } @@ -125,7 +127,7 @@ impl Plugin for ContentFilterPlugin { if filter.matches(bytes) { let mut response = SgResponse::with_code_empty(StatusCode::BAD_REQUEST); response.extensions_mut().insert(ContentFilterForbiddenReport { - forbidden_reason: format!("forbidden rule matched: {filter}") , + forbidden_reason: format!("forbidden rule matched: {filter}"), }); return Ok(response); } diff --git a/backend/gateways/spacegate-plugins/src/plugin/notify.rs b/backend/gateways/spacegate-plugins/src/plugin/notify.rs index f29f9d53e..a460bb78a 100644 --- a/backend/gateways/spacegate-plugins/src/plugin/notify.rs +++ b/backend/gateways/spacegate-plugins/src/plugin/notify.rs @@ -15,9 +15,9 @@ use spacegate_shell::{ BoxError, SgRequest, SgRequestExt, SgResponse, }; use tardis::{ + log as tracing, regex::{self, Regex}, serde_json, - log as tracing, }; use crate::extension::{ @@ -32,13 +32,13 @@ pub struct NotifyPluginConfig { /// - rate_limit: rate limit notification /// - count: number of requests /// - time_window: time window - /// + /// /// - tamper: tamper notification - /// + /// /// - unauthorized_operation: unauthorized operation notification - /// + /// /// - cert_lock: cert lock notification - /// + /// /// - content_filter_forbidden: content filter forbidden notification /// - reason: forbidden reason templates: HashMap, diff --git a/backend/gateways/spacegate-plugins/src/utils.rs b/backend/gateways/spacegate-plugins/src/utils.rs index 44c6f0366..af5c5586c 100644 --- a/backend/gateways/spacegate-plugins/src/utils.rs +++ b/backend/gateways/spacegate-plugins/src/utils.rs @@ -18,7 +18,7 @@ pub fn parse_duration(duration: &str) -> Result { duration = rest; // Parse unit - let (unit, rest) = match duration.find(|c: char| !c.is_alphabetic() && c != ' ') { + let (unit, rest) = match duration.find(|c: char| !c.is_alphabetic() && c != ' ') { Some(index) => duration.split_at(index), None => (duration, ""), }; @@ -29,7 +29,7 @@ pub fn parse_duration(duration: &str) -> Result { "ms" | "millisecond" => Duration::from_millis(number), "s" | "second" => Duration::from_secs(number), "m" | "min" => Duration::from_secs(number * 60), - "h" | "hour" => Duration::from_secs(number * 60 * 60), + "h" | "hour" => Duration::from_secs(number * 60 * 60), "d" | "day" => Duration::from_secs(number * 60 * 60 * 24), _ => return Err(format!("Invalid unit: {}", unit).into()), }; @@ -66,6 +66,5 @@ mod test { "1ns1us1ms1s1m1h1d" => Duration::from_nanos(1) + Duration::from_micros(1) + Duration::from_millis(1) + Duration::from_secs(1) + Duration::from_secs(60) + Duration::from_secs(60 * 60) + Duration::from_secs(60 * 60 * 24), "1d 1h 1min 1s 1ms 1us 1ns" => Duration::from_secs(60 * 60 * 24) + Duration::from_secs(60 * 60) + Duration::from_secs(60) + Duration::from_secs(1) + Duration::from_millis(1) + Duration::from_micros(1) + Duration::from_nanos(1), } - } -} \ No newline at end of file +} diff --git a/backend/middlewares/flow/src/api/ci/flow_ci_inst_api.rs b/backend/middlewares/flow/src/api/ci/flow_ci_inst_api.rs index 56b7903be..e5750d3b2 100644 --- a/backend/middlewares/flow/src/api/ci/flow_ci_inst_api.rs +++ b/backend/middlewares/flow/src/api/ci/flow_ci_inst_api.rs @@ -279,4 +279,14 @@ impl FlowCiInstApi { ctx.0.execute_task().await?; TardisResp::ok(result) } + + /// sync instance status to search + /// + /// 同步状态信息 + #[oai(path = "/status/sync", method = "get")] + async fn sync_status(&self, _ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult { + let funs = flow_constants::get_tardis_inst(); + FlowInstServ::sync_status(&funs).await?; + TardisResp::ok(Void {}) + } } diff --git a/backend/middlewares/flow/src/api/ci/flow_ci_model_api.rs b/backend/middlewares/flow/src/api/ci/flow_ci_model_api.rs index 03c02abf3..a00a464e5 100644 --- a/backend/middlewares/flow/src/api/ci/flow_ci_model_api.rs +++ b/backend/middlewares/flow/src/api/ci/flow_ci_model_api.rs @@ -1,8 +1,7 @@ use std::collections::HashMap; use crate::dto::flow_model_dto::{ - FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelCopyOrReferenceCiReq, FlowModelExistRelByTemplateIdsReq, FlowModelFilterReq, FlowModelFindRelStateResp, - FlowModelKind, FlowModelSyncModifiedFieldReq, + FlowModelAggResp, FlowModelCopyOrReferenceCiReq, FlowModelExistRelByTemplateIdsReq, FlowModelFilterReq, FlowModelFindRelStateResp, FlowModelKind, FlowModelSyncModifiedFieldReq, }; use crate::flow_constants; use crate::serv::flow_inst_serv::FlowInstServ; @@ -274,7 +273,7 @@ impl FlowCiModelApi { &ctx.0, ) .await - .unwrap() + .unwrap_or_default() .into_iter() .map(|model| model.tag.clone()) .collect_vec(); diff --git a/backend/middlewares/flow/src/dto/flow_inst_dto.rs b/backend/middlewares/flow/src/dto/flow_inst_dto.rs index f09c1078b..8969f9ea4 100644 --- a/backend/middlewares/flow/src/dto/flow_inst_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_inst_dto.rs @@ -345,7 +345,7 @@ pub struct FlowInstFindNextTransitionsReq { } /// 获取实例下一个动作列表请求 -#[derive(Serialize, Deserialize, Debug, poem_openapi::Object, Clone)] +#[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object, Clone)] pub struct FlowInstFindNextTransitionResp { /// Associated [flow_transition](super::flow_transition_dto::FlowTransitionDetailResp) id /// @@ -376,7 +376,7 @@ pub struct FlowInstFindNextTransitionResp { } /// 获取实例状态及流转信息的请求 -#[derive(Serialize, Deserialize, Debug, poem_openapi::Object)] +#[derive(Serialize, Deserialize, Default, Debug, poem_openapi::Object, Clone)] pub struct FlowInstFindStateAndTransitionsReq { /// 实例ID pub flow_inst_id: String, diff --git a/backend/middlewares/flow/src/dto/flow_model_version_dto.rs b/backend/middlewares/flow/src/dto/flow_model_version_dto.rs index ea7f15bd8..c507efe44 100644 --- a/backend/middlewares/flow/src/dto/flow_model_version_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_model_version_dto.rs @@ -160,7 +160,7 @@ pub struct FlowModelVersionDetailResp { impl FlowModelVersionDetailResp { pub fn states(&self) -> Vec { match &self.states { - Some(states) => TardisFuns::json.json_to_obj(states.clone()).unwrap(), + Some(states) => TardisFuns::json.json_to_obj(states.clone()).unwrap_or_default(), None => vec![], } } diff --git a/backend/middlewares/flow/src/dto/flow_transition_dto.rs b/backend/middlewares/flow/src/dto/flow_transition_dto.rs index a14f70e74..668a07391 100644 --- a/backend/middlewares/flow/src/dto/flow_transition_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_transition_dto.rs @@ -197,7 +197,7 @@ pub struct FlowTransitionDetailResp { impl FlowTransitionDetailResp { pub fn guard_by_other_conds(&self) -> Option>> { - if self.guard_by_other_conds.is_array() && !&self.guard_by_other_conds.as_array().unwrap().is_empty() { + if self.guard_by_other_conds.is_array() && !&self.guard_by_other_conds.as_array().filter(|conds| conds.is_empty()).is_some() { Some(TardisFuns::json.json_to_obj(self.guard_by_other_conds.clone()).unwrap_or_default()) } else { None @@ -205,7 +205,7 @@ impl FlowTransitionDetailResp { } pub fn vars_collect(&self) -> Option> { - if self.vars_collect.is_array() && !&self.vars_collect.as_array().unwrap().is_empty() { + if self.vars_collect.is_array() && !&self.vars_collect.as_array().filter(|conds| conds.is_empty()).is_some() { Some(TardisFuns::json.json_to_obj(self.vars_collect.clone()).unwrap_or_default()) } else { None @@ -213,7 +213,7 @@ impl FlowTransitionDetailResp { } pub fn action_by_post_changes(&self) -> Vec { - if self.action_by_post_changes.is_array() && !&self.action_by_post_changes.as_array().unwrap().is_empty() { + if self.action_by_post_changes.is_array() && !&self.action_by_post_changes.as_array().filter(|conds| conds.is_empty()).is_some() { TardisFuns::json.json_to_obj(self.action_by_post_changes.clone()).unwrap_or_default() } else { vec![] @@ -221,7 +221,7 @@ impl FlowTransitionDetailResp { } pub fn action_by_front_changes(&self) -> Vec { - if self.action_by_front_changes.is_array() && !&self.action_by_front_changes.as_array().unwrap().is_empty() { + if self.action_by_front_changes.is_array() && !&self.action_by_front_changes.as_array().filter(|conds| conds.is_empty()).is_some() { TardisFuns::json.json_to_obj(self.action_by_front_changes.clone()).unwrap_or_default() } else { vec![] @@ -329,7 +329,7 @@ impl From for FlowTransitionActionChangeAgg { kind: value.kind, var_change_info: None, state_change_info: Some(FlowTransitionActionByStateChangeInfo { - obj_tag: value.obj_tag.unwrap(), + obj_tag: value.obj_tag.unwrap_or_default(), obj_tag_rel_kind: value.obj_tag_rel_kind, describe: value.describe, obj_current_state_id: value.obj_current_state_id, @@ -454,7 +454,7 @@ pub struct StateChangeCondition { } /// 筛选条件的配置项 -#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, poem_openapi::Object, sea_orm::FromJsonQueryResult)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default, poem_openapi::Object, sea_orm::FromJsonQueryResult)] pub struct StateChangeConditionItem { /// 对象Tag。为空时,代表触发的业务对象为当前操作的业务对象。有值时,代表触发的业务对象为当前操作的业务对象的关联对象。 /// 例:值为req,则代表触发的业务对象为当前操作对象所关联的需求对象。 @@ -470,8 +470,9 @@ pub struct StateChangeConditionItem { } /// 实际规则的条件类型 -#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, poem_openapi::Enum)] +#[derive(Serialize, Deserialize, Clone, PartialEq, Debug, Default, poem_openapi::Enum)] pub enum StateChangeConditionOp { + #[default] And, Or, } @@ -669,7 +670,10 @@ impl FlowTransitionFrontActionInfoRelevanceRelation { } left_value >= interval[0] && left_value <= interval[1] } - FlowTransitionFrontActionInfoRelevanceRelation::IsNullOrEmpty => {let s = left_value.as_str().to_string(); s.is_empty() || s == "[]" || s == "{}"}, + FlowTransitionFrontActionInfoRelevanceRelation::IsNullOrEmpty => { + let s = left_value.as_str().to_string(); + s.is_empty() || s == "[]" || s == "{}" + } FlowTransitionFrontActionInfoRelevanceRelation::IsNotNull => !left_value.as_str().to_string().is_empty(), } } diff --git a/backend/middlewares/flow/src/lib.rs b/backend/middlewares/flow/src/lib.rs index 0fdfabd26..904c8122c 100644 --- a/backend/middlewares/flow/src/lib.rs +++ b/backend/middlewares/flow/src/lib.rs @@ -7,4 +7,4 @@ pub mod flow_config; pub mod flow_constants; pub mod flow_initializer; mod helper; -mod serv; \ No newline at end of file +mod serv; diff --git a/backend/middlewares/flow/src/serv/clients/kv_client.rs b/backend/middlewares/flow/src/serv/clients/kv_client.rs index ea2ca6fce..c3b025d1f 100644 --- a/backend/middlewares/flow/src/serv/clients/kv_client.rs +++ b/backend/middlewares/flow/src/serv/clients/kv_client.rs @@ -20,23 +20,22 @@ impl FlowKvClient { pub async fn get_role_id(original_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { let mut role_id = "".to_string(); if let Some(role_id_prefix) = original_id.split(':').collect_vec().first() { - role_id = SpiKvClient::match_items_by_key_prefix(format!("__k_n__:iam_role:{}", role_id_prefix), None, 1, 999, None, funs, ctx).await? - .map(|resp| { - resp.records.into_iter().filter(|record| ctx.own_paths.contains(&record.own_paths)).collect_vec() - }) - .map(|records| { - if let Some(item) = records.iter().find(|r| r.own_paths == ctx.own_paths) { - return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); - } - if let Some(item) = records.iter().find(|r| r.own_paths == rbum_scope_helper::get_path_item(1, &ctx.own_paths).unwrap_or_default()) { - return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); - } - if let Some(item) = records.iter().find(|r| r.own_paths.is_empty()) { - return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); - } - "".to_string() - }) - .unwrap_or_default(); + role_id = SpiKvClient::match_items_by_key_prefix(format!("__k_n__:iam_role:{}", role_id_prefix), None, 1, 999, None, funs, ctx) + .await? + .map(|resp| resp.records.into_iter().filter(|record| ctx.own_paths.contains(&record.own_paths)).collect_vec()) + .map(|records| { + if let Some(item) = records.iter().find(|r| r.own_paths == ctx.own_paths) { + return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); + } + if let Some(item) = records.iter().find(|r| r.own_paths == rbum_scope_helper::get_path_item(1, &ctx.own_paths).unwrap_or_default()) { + return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); + } + if let Some(item) = records.iter().find(|r| r.own_paths.is_empty()) { + return item.key.split("__k_n__:iam_role:").collect_vec().pop().map(|s| s.to_string()).unwrap_or_default(); + } + "".to_string() + }) + .unwrap_or_default(); } Ok(role_id) diff --git a/backend/middlewares/flow/src/serv/clients/search_client.rs b/backend/middlewares/flow/src/serv/clients/search_client.rs index a6e8fe5fc..1433407e0 100644 --- a/backend/middlewares/flow/src/serv/clients/search_client.rs +++ b/backend/middlewares/flow/src/serv/clients/search_client.rs @@ -9,29 +9,23 @@ use bios_sdk_invoke::{ }, }; use itertools::Itertools; -use serde_json::json; +use serde_json::{json, Value}; use tardis::{ basic::{dto::TardisContext, field::TrimString, result::TardisResult}, log::{debug, error}, tokio, web::{poem_openapi::types::ToJSON, web_resp::TardisPage}, - TardisFuns, TardisFunsInst, + TardisFunsInst, }; use crate::{ dto::{ - flow_inst_dto::{FlowInstDetailResp, FlowInstFilterReq}, - flow_model_dto::{FlowModelDetailResp, FlowModelFilterReq, FlowModelRelTransitionExt}, - flow_model_version_dto::FlowModelVersionFilterReq, + flow_inst_dto::FlowInstDetailResp, + flow_model_dto::{FlowModelDetailResp, FlowModelFilterReq}, flow_state_dto::FlowGuardConf, }, flow_constants, - serv::{ - flow_inst_serv::FlowInstServ, - flow_model_serv::FlowModelServ, - flow_model_version_serv::FlowModelVersionServ, - flow_rel_serv::{FlowRelKind, FlowRelServ}, - }, + serv::{flow_inst_serv::FlowInstServ, flow_model_serv::FlowModelServ}, }; const SEARCH_MODEL_TAG: &str = "flow_model"; @@ -40,49 +34,8 @@ const SEARCH_INSTANCE_TAG: &str = "flow_approve_inst"; pub struct FlowSearchClient; impl FlowSearchClient { - pub async fn modify_business_obj_search(rel_business_obj_id: &str, tag: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + pub async fn modify_business_obj_search(rel_business_obj_id: &str, tag: &str, ext: Value, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { let tag_search_map = Self::get_tag_search_map(); - let rel_version_ids = FlowInstServ::find_detail_items( - &FlowInstFilterReq { - rel_business_obj_ids: Some(vec![rel_business_obj_id.to_string()]), - main: Some(false), - finish: Some(false), - ..Default::default() - }, - funs, - ctx, - ) - .await? - .into_iter() - .map(|inst| inst.rel_flow_version_id) - .collect_vec(); - let mut rel_transition_names = vec![]; - for rel_version_id in rel_version_ids { - if let Some(rel_model_id) = FlowModelVersionServ::find_one_item( - &FlowModelVersionFilterReq { - basic: RbumBasicFilterReq { - ids: Some(vec![rel_version_id]), - with_sub_own_paths: true, - own_paths: Some("".to_string()), - ..Default::default() - }, - ..Default::default() - }, - funs, - ctx, - ) - .await? - .map(|version| version.rel_model_id) - { - let rel_transition_ext = FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTransition, &rel_model_id, None, None, funs, ctx) - .await? - .pop() - .map(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default()); - if let Some(ext) = rel_transition_ext { - rel_transition_names.push(ext.to_string()); - } - } - } if let Some(table) = tag_search_map.get(tag) { SpiSearchClient::modify_item_and_name( table, @@ -96,9 +49,7 @@ impl FlowSearchClient { own_paths: None, create_time: None, update_time: None, - ext: Some(json!({ - "rel_transitions": rel_transition_names, - })), + ext: Some(ext), ext_override: None, visit_keys: None, kv_disable: None, diff --git a/backend/middlewares/flow/src/serv/flow_event_serv.rs b/backend/middlewares/flow/src/serv/flow_event_serv.rs index f391ae0b7..009e39913 100644 --- a/backend/middlewares/flow/src/serv/flow_event_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_event_serv.rs @@ -101,7 +101,7 @@ impl FlowEventServ { if flow_inst_detail.current_vars.is_none() || conditions.is_empty() { return Ok(false); } - let current_vars = flow_inst_detail.current_vars.clone().unwrap(); + let current_vars = flow_inst_detail.current_vars.clone().unwrap_or_default(); for condition in conditions { if !Self::do_check_front_condition(¤t_vars, &condition)? { return Ok(false); @@ -215,11 +215,10 @@ impl FlowEventServ { .find(|state| state.id == flow_inst_detail.current_state_id) .ok_or_else(|| funs.err().not_found("flow_event", "do_front_change", "illegal response", "404-flow-transition-not-found"))? .transitions; - let next_flow_transition = model_transition.iter().find(|trans| trans.id == flow_transition_id); - if next_flow_transition.is_none() { - return Err(funs.err().not_found("flow_inst", "transfer", "no transferable state", "404-flow-inst-transfer-state-not-found")); - } - let next_flow_transition = next_flow_transition.unwrap(); + let next_flow_transition = model_transition + .iter() + .find(|trans| trans.id == flow_transition_id) + .ok_or_else(|| funs.err().not_found("flow_inst", "transfer", "no transferable state", "404-flow-inst-transfer-state-not-found"))?; let prev_flow_state = FlowStateServ::get_item( &next_flow_transition.from_flow_state_id, &FlowStateFilterReq { @@ -260,17 +259,17 @@ impl FlowEventServ { match post_change.kind { FlowTransitionActionChangeKind::Var => { if let Some(mut change_info) = post_change.var_change_info { - if change_info.changed_kind.is_some() { - match change_info.changed_kind.clone().unwrap() { + if let Some(changed_kind) = &change_info.changed_kind { + match changed_kind { FlowTransitionActionByVarChangeInfoChangedKind::AutoGetOperateTime => { change_info.changed_val = Some(json!(Utc::now().to_rfc3339_opts(SecondsFormat::Millis, true))); change_info.changed_kind = Some(FlowTransitionActionByVarChangeInfoChangedKind::ChangeContent); } FlowTransitionActionByVarChangeInfoChangedKind::AddOrSub => { if change_info.changed_val.is_some() - && change_info.changed_val.clone().unwrap().is_object() - && change_info.changed_val.clone().unwrap().as_object().unwrap().get("value").is_some() - && change_info.changed_val.clone().unwrap().as_object().unwrap().get("op").is_some() + && change_info.changed_val.clone().unwrap_or(json!({})).is_object() + && change_info.changed_val.clone().unwrap_or(json!({})).as_object().filter(|map| map.get("value").is_some()).is_some() + && change_info.changed_val.clone().unwrap_or(json!({})).as_object().filter(|map| map.get("op").is_some()).is_some() { let original_value = if let Some(custom_value) = FlowInstServ::find_var_by_inst_id(flow_inst_detail, &format!("custom_{}", change_info.var_name), funs, ctx).await? @@ -285,29 +284,39 @@ impl FlowEventServ { let target_value = change_info .changed_val .clone() - .unwrap() + .unwrap_or(json!({})) .as_object() - .unwrap() - .get("value") - .unwrap() + .map(|map| map.get("value").cloned().unwrap_or(json!({}))) + .unwrap_or(json!({})) .as_str() .unwrap_or_default() .parse::() .unwrap_or_default(); - let changed_op = change_info.changed_val.clone().unwrap().as_object().unwrap().get("op").unwrap().as_str().unwrap_or_default().to_string(); + let changed_op = change_info + .changed_val + .clone() + .unwrap_or(json!({})) + .as_object() + .map(|map| map.get("op").cloned().unwrap_or(json!({}))) + .unwrap_or(json!({})) + .as_str() + .unwrap_or_default() + .to_string(); if let Some(original_value) = original_value { change_info.changed_kind = Some(FlowTransitionActionByVarChangeInfoChangedKind::ChangeContent); match changed_op.as_str() { "add" => { change_info.changed_val = Some(json!( - (Decimal::from_str(&original_value.as_str().unwrap_or_default().parse::().unwrap_or_default().to_string()).unwrap() - + Decimal::from_str(&target_value.to_string()).unwrap()) + (Decimal::from_str(&original_value.as_str().unwrap_or_default().parse::().unwrap_or_default().to_string()) + .unwrap_or_default() + + Decimal::from_str(&target_value.to_string()).unwrap_or_default()) )) } "sub" => { change_info.changed_val = Some(json!( - (Decimal::from_str(&original_value.as_str().unwrap_or_default().parse::().unwrap_or_default().to_string()).unwrap() - - Decimal::from_str(&target_value.to_string()).unwrap()) + (Decimal::from_str(&original_value.as_str().unwrap_or_default().parse::().unwrap_or_default().to_string()) + .unwrap_or_default() + - Decimal::from_str(&target_value.to_string()).unwrap_or_default()) )) } _ => {} @@ -318,6 +327,7 @@ impl FlowEventServ { _ => {} }; } + let rel_tag = change_info.obj_tag.unwrap_or_default(); if !rel_tag.is_empty() { let mut resp = FlowExternalServ::do_fetch_rel_obj( @@ -330,7 +340,7 @@ impl FlowEventServ { ) .await?; if !resp.rel_bus_objs.is_empty() { - for rel_bus_obj_id in resp.rel_bus_objs.pop().unwrap().rel_bus_obj_ids { + for rel_bus_obj_id in resp.rel_bus_objs.pop().unwrap_or_default().rel_bus_obj_ids { let inst_id = FlowInstServ::get_inst_ids_by_rel_business_obj_id(vec![rel_bus_obj_id.clone()], Some(true), funs, ctx).await?.pop().unwrap_or_default(); FlowExternalServ::do_modify_field( @@ -385,7 +395,8 @@ impl FlowEventServ { ) .await?; if !resp.rel_bus_objs.is_empty() { - let inst_ids = Self::find_inst_ids_by_rel_obj_ids(&flow_model, resp.rel_bus_objs.pop().unwrap().rel_bus_obj_ids, &change_info, funs, ctx).await?; + let inst_ids = + Self::find_inst_ids_by_rel_obj_ids(&flow_model, resp.rel_bus_objs.pop().unwrap_or_default().rel_bus_obj_ids, &change_info, funs, ctx).await?; Self::do_modify_state_by_post_action(inst_ids, &change_info, modified_instance_transations.clone(), funs, ctx).await?; } } @@ -435,7 +446,7 @@ impl FlowEventServ { let mut rel_tags = vec![]; for condition_item in change_condition.conditions.iter() { if condition_item.obj_tag.is_some() && !condition_item.state_id.is_empty() { - rel_tags.push((condition_item.obj_tag.clone().unwrap(), condition_item.obj_tag_rel_kind.clone())); + rel_tags.push((condition_item.obj_tag.clone().unwrap_or_default(), condition_item.obj_tag_rel_kind.clone())); } } let inst_id = FlowInstServ::get_inst_ids_by_rel_business_obj_id(vec![rel_obj_id.clone()], Some(true), funs, ctx).await?.pop().unwrap_or_default(); @@ -450,8 +461,9 @@ impl FlowEventServ { let condition = change_condition .conditions .iter() - .find(|condition| condition.obj_tag.is_some() && condition.obj_tag.clone().unwrap() == rel_bus_obj.rel_tag.clone()) - .unwrap(); + .find(|condition| condition.obj_tag.is_some() && condition.obj_tag.clone().unwrap_or_default() == rel_bus_obj.rel_tag.clone()) + .cloned() + .unwrap_or_default(); let rel_obj_ids = Self::filter_rel_obj_ids_by_state(&rel_bus_obj.rel_bus_obj_ids, &Some(condition.state_id.clone()), funs, ctx).await?; match condition.op { StateChangeConditionOp::And => { diff --git a/backend/middlewares/flow/src/serv/flow_external_serv.rs b/backend/middlewares/flow/src/serv/flow_external_serv.rs index f32c2ada6..a757b368c 100644 --- a/backend/middlewares/flow/src/serv/flow_external_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_external_serv.rs @@ -1,7 +1,10 @@ use bios_sdk_invoke::{clients::spi_kv_client::SpiKvClient, invoke_constants::TARDIS_CONTEXT}; use itertools::Itertools; use tardis::{ - basic::{dto::TardisContext, result::TardisResult}, chrono::Utc, log::debug, tokio, TardisFuns, TardisFunsInst + basic::{dto::TardisContext, result::TardisResult}, + chrono::Utc, + log::debug, + tokio, TardisFuns, TardisFunsInst, }; use crate::{ diff --git a/backend/middlewares/flow/src/serv/flow_inst_serv.rs b/backend/middlewares/flow/src/serv/flow_inst_serv.rs index 65b04f3be..ebaff2f08 100644 --- a/backend/middlewares/flow/src/serv/flow_inst_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_inst_serv.rs @@ -11,7 +11,6 @@ use bios_basic::rbum::{ rbum_item_serv::{RbumItemCrudOperation, RBUM_ITEM_TABLE}, }, }; -use bios_sdk_invoke::dto::search_item_dto::{SearchItemQueryReq, SearchItemSearchCtxReq, SearchItemSearchPageReq, SearchItemSearchReq}; use itertools::Itertools; use serde_json::json; use tardis::{ @@ -32,16 +31,23 @@ use tardis::{ use crate::{ domain::{flow_inst, flow_model_version}, dto::{ - flow_cond_dto::BasicQueryCondInfo, flow_external_dto::{FlowExternalCallbackOp, FlowExternalParams}, flow_inst_dto::{ + flow_cond_dto::BasicQueryCondInfo, + flow_external_dto::{FlowExternalCallbackOp, FlowExternalParams}, + flow_inst_dto::{ FLowInstStateApprovalConf, FLowInstStateConf, FLowInstStateFormConf, FlowApprovalResultKind, FlowInstAbortReq, FlowInstArtifacts, FlowInstArtifactsModifyReq, FlowInstBatchBindReq, FlowInstBatchBindResp, FlowInstCommentInfo, FlowInstCommentReq, FlowInstDetailResp, FlowInstFilterReq, FlowInstFindNextTransitionResp, FlowInstFindNextTransitionsReq, FlowInstFindStateAndTransitionsReq, FlowInstFindStateAndTransitionsResp, FlowInstOperateReq, FlowInstQueryKind, FlowInstSearchPageReq, FlowInstSearchReq, FlowInstSearchResp, FlowInstSearchSortReq, FlowInstStartReq, FlowInstStateKind, FlowInstSummaryResp, FlowInstSummaryResult, FlowInstTransferReq, FlowInstTransferResp, FlowInstTransitionInfo, FlowOperationContext, - }, flow_model_dto::{FlowModelAggResp, FlowModelRelTransitionExt}, flow_model_version_dto::{FlowModelVersionDetailResp, FlowModelVersionFilterReq}, flow_state_dto::{ + }, + flow_model_dto::{FlowModelAggResp, FlowModelRelTransitionExt}, + flow_model_version_dto::{FlowModelVersionDetailResp, FlowModelVersionFilterReq}, + flow_state_dto::{ FLowStateKindConf, FlowStateCountersignKind, FlowStateFilterReq, FlowStateKind, FlowStateOperatorKind, FlowStateRelModelExt, FlowStatusAutoStrategyKind, FlowStatusMultiApprovalKind, FlowSysStateKind, - }, flow_transition_dto::FlowTransitionDetailResp, flow_var_dto::FillType + }, + flow_transition_dto::FlowTransitionDetailResp, + flow_var_dto::FillType, }, flow_constants, helper::loop_check_helper, @@ -175,7 +181,17 @@ impl FlowInstServ { ctx, ) .await?; - FlowSearchClient::modify_business_obj_search(&start_req.rel_business_obj_id, &flow_model.tag, funs, ctx).await?; + let rel_transition_names = Self::get_rel_transitions(&start_req.rel_business_obj_id, funs, ctx).await?.into_iter().map(|rel| rel.name).collect_vec(); + FlowSearchClient::modify_business_obj_search( + &start_req.rel_business_obj_id, + &flow_model.tag, + json!({ + "rel_transitions": rel_transition_names, + }), + funs, + ctx, + ) + .await?; let inst = Self::get(&inst_id, funs, ctx).await?; FlowLogServ::add_start_log(start_req, &inst, &create_vars, &flow_model, ctx).await?; FlowLogServ::add_start_dynamic_log(start_req, &inst, &create_vars, &flow_model, ctx).await?; @@ -217,8 +233,11 @@ impl FlowInstServ { let current_state_id = FlowStateServ::match_state_id_by_name(&flow_model.current_version_id, &rel_business_obj.current_state_name.clone().unwrap_or_default(), funs, ctx).await?; - let mut inst_id = Self::get_inst_ids_by_rel_business_obj_id(vec![rel_business_obj.rel_business_obj_id.clone().unwrap_or_default()], Some(true), funs, ctx).await?.pop(); - if inst_id.is_none() { + let inst_id = if let Some(inst_id) = + Self::get_inst_ids_by_rel_business_obj_id(vec![rel_business_obj.rel_business_obj_id.clone().unwrap_or_default()], Some(true), funs, ctx).await?.pop() + { + inst_id + } else { let id = TardisFuns::field.nanoid(); let flow_inst: flow_inst::ActiveModel = flow_inst::ActiveModel { id: Set(id.clone()), @@ -236,13 +255,13 @@ impl FlowInstServ { ..Default::default() }; funs.db().insert_one(flow_inst, ¤t_ctx).await?; - inst_id = Some(id); - } - let current_state_name = Self::get(inst_id.as_ref().unwrap(), funs, ¤t_ctx).await?.current_state_name.unwrap_or_default(); + id + }; + let current_state_name = Self::get(&inst_id, funs, ¤t_ctx).await?.current_state_name.unwrap_or_default(); result.push(FlowInstBatchBindResp { rel_business_obj_id: rel_business_obj.rel_business_obj_id.clone().unwrap_or_default(), current_state_name, - inst_id, + inst_id: Some(inst_id), }); } @@ -432,16 +451,26 @@ impl FlowInstServ { let flow_inst_detail = Self::get(flow_inst_id, funs, ctx).await?; if !flow_inst_detail.main { FlowLogServ::add_finish_log(&flow_inst_detail, funs, ctx).await?; - FlowSearchClient::modify_business_obj_search(&flow_inst_detail.rel_business_obj_id, &flow_inst_detail.tag, funs, ctx).await?; + let rel_transition_names = Self::get_rel_transitions(&flow_inst_detail.rel_business_obj_id, funs, ctx).await?.into_iter().map(|rel| rel.name).collect_vec(); + FlowSearchClient::modify_business_obj_search( + &flow_inst_detail.rel_business_obj_id, + &flow_inst_detail.tag, + json!({ + "rel_transitions": rel_transition_names, + }), + funs, + ctx, + ) + .await?; FlowSearchClient::async_add_or_modify_instance_search(&flow_inst_detail.id, Box::new(true), funs, ctx).await?; } Ok(()) } pub async fn get(flow_inst_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { - let mut flow_insts = Self::find_detail(vec![flow_inst_id.to_string()], None, None, funs, ctx).await?; - if flow_insts.len() == 1 { - Ok(flow_insts.pop().unwrap()) + let flow_insts = Self::find_detail(vec![flow_inst_id.to_string()], None, None, funs, ctx).await?; + if let Some(flow_inst) = flow_insts.into_iter().next() { + Ok(flow_inst) } else { Err(funs.err().not_found("flow_inst", "get", &format!("flow instance {} not found", flow_inst_id), "404-flow-inst-not-found")) } @@ -555,8 +584,8 @@ impl FlowInstServ { rel_state_table.clone(), Cond::all() .add(Expr::col((rel_state_table.clone(), ID_FIELD.clone())).equals((flow_inst::Entity, flow_inst::Column::CurrentStateId))) - .add(Expr::col((rel_state_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap())) - .add(Expr::col((rel_state_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap())), + .add(Expr::col((rel_state_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap_or_default())) + .add(Expr::col((rel_state_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap_or_default())), ) .join_as( JoinType::LeftJoin, @@ -570,8 +599,8 @@ impl FlowInstServ { rel_model_version_table.clone(), Cond::all() .add(Expr::col((rel_model_version_table.clone(), ID_FIELD.clone())).equals((flow_inst::Entity, flow_inst::Column::RelFlowVersionId))) - .add(Expr::col((rel_model_version_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowModelVersionServ::get_rbum_kind_id().unwrap())) - .add(Expr::col((rel_model_version_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowModelVersionServ::get_rbum_domain_id().unwrap())), + .add(Expr::col((rel_model_version_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowModelVersionServ::get_rbum_kind_id().unwrap_or_default())) + .add(Expr::col((rel_model_version_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowModelVersionServ::get_rbum_domain_id().unwrap_or_default())), ) .join_as( JoinType::LeftJoin, @@ -627,7 +656,7 @@ impl FlowInstServ { rel_flow_model_name: inst.rel_flow_model_name, tag: inst.tag, main: inst.main, - create_vars: inst.create_vars.map(|create_vars| TardisFuns::json.json_to_obj(create_vars).unwrap()), + create_vars: inst.create_vars.map(|create_vars| TardisFuns::json.json_to_obj(create_vars).unwrap_or_default()), create_ctx: inst.create_ctx, create_time: inst.create_time, update_time: inst.update_time, @@ -636,9 +665,9 @@ impl FlowInstServ { finish_abort: inst.finish_abort, output_message: inst.output_message, own_paths: inst.own_paths, - transitions: inst.transitions.map(|transitions| TardisFuns::json.json_to_obj(transitions).unwrap()), + transitions: inst.transitions.map(|transitions| TardisFuns::json.json_to_obj(transitions).unwrap_or_default()), artifacts: artifacts.clone(), - comments: inst.comments.map(|comments| TardisFuns::json.json_to_obj(comments).unwrap()), + comments: inst.comments.map(|comments| TardisFuns::json.json_to_obj(comments).unwrap_or_default()), rel_transition, current_state_id: inst.current_state_id.clone(), current_state_name: inst.current_state_name, @@ -659,7 +688,7 @@ impl FlowInstServ { inst.finish_time.is_some(), ctx, ), - current_vars: inst.current_vars.map(|current_vars| TardisFuns::json.json_to_obj(current_vars).unwrap()), + current_vars: inst.current_vars.map(|current_vars| TardisFuns::json.json_to_obj(current_vars).unwrap_or_default()), rel_business_obj_id: inst.rel_business_obj_id, } }) @@ -723,10 +752,10 @@ impl FlowInstServ { rel_flow_version_id: inst.rel_flow_version_id, rel_flow_model_id: inst.rel_flow_model_id, rel_flow_model_name: inst.rel_flow_model_name, - create_ctx: TardisFuns::json.json_to_obj(inst.create_ctx).unwrap(), + create_ctx: TardisFuns::json.json_to_obj(inst.create_ctx).unwrap_or_default(), create_time: inst.create_time, update_time: inst.update_time, - finish_ctx: inst.finish_ctx.map(|finish_ctx| TardisFuns::json.json_to_obj(finish_ctx).unwrap()), + finish_ctx: inst.finish_ctx.map(|finish_ctx| TardisFuns::json.json_to_obj(finish_ctx).unwrap_or_default()), finish_time: inst.finish_time, finish_abort: inst.finish_abort.is_some(), output_message: inst.output_message, @@ -778,14 +807,22 @@ impl FlowInstServ { flow_insts .iter() .map(|flow_inst| async { - let req = find_req.iter().find(|req| req.flow_inst_id == flow_inst.id).unwrap(); - let flow_model_version = flow_model_versions.iter().find(|version| version.id == flow_inst.rel_flow_version_id).unwrap(); - let rel_flow_versions = rel_flow_version_map.get(&flow_inst.tag).unwrap().clone(); - Self::do_find_next_transitions(flow_inst, flow_model_version, None, &req.vars, rel_flow_versions, false, funs, ctx).await.unwrap() + if let (Some(req), Some(flow_model_version), Some(rel_flow_versions)) = ( + find_req.iter().find(|req| req.flow_inst_id == flow_inst.id), + flow_model_versions.iter().find(|version| version.id == flow_inst.rel_flow_version_id), + rel_flow_version_map.get(&flow_inst.tag).cloned(), + ) { + Self::do_find_next_transitions(flow_inst, flow_model_version, None, &req.vars, rel_flow_versions, false, funs, ctx).await.ok() + } else { + None + } }) .collect_vec(), ) - .await; + .await + .into_iter() + .flatten() + .collect_vec(); // 若当前数据项存在未结束的审批流,则清空其中的transitions let unfinished_approve_flow_inst_ids = Self::find_detail_items( &FlowInstFilterReq { @@ -799,7 +836,7 @@ impl FlowInstServ { ) .await? .into_iter() - .map(|inst| flow_insts.iter().find(|flow_inst| flow_inst.rel_business_obj_id == inst.rel_business_obj_id).unwrap().id.clone()) + .filter_map(|inst| flow_insts.iter().find(|flow_inst| flow_inst.rel_business_obj_id == inst.rel_business_obj_id).map(|r| r.id.clone())) .collect_vec(); for item in state_and_next_transitions.iter_mut() { if unfinished_approve_flow_inst_ids.contains(&item.flow_inst_id) { @@ -960,17 +997,17 @@ impl FlowInstServ { .await? .into_iter() .find(|trans| trans.id == transfer_req.flow_transition_id) - .unwrap() - .from_flow_state_id, + .map(|tran| tran.from_flow_state_id) + .unwrap_or_default(), ctx, funs, ) .await; } let version_transition = FlowTransitionServ::find_transitions(&flow_model_version.id, None, funs, ctx).await?; - let next_transition_detail = version_transition.iter().find(|trans| trans.id == transfer_req.flow_transition_id).unwrap().to_owned(); - let next_flow_transition = next_flow_transition.unwrap(); + let next_flow_transition = next_flow_transition.unwrap_or_default(); + let next_transition_detail = version_transition.iter().find(|trans| trans.id == next_flow_transition.next_flow_transition_id).cloned().unwrap_or_default(); let prev_flow_state = FlowStateServ::get_item( &flow_inst_detail.current_state_id, &FlowStateFilterReq { @@ -1079,7 +1116,17 @@ impl FlowInstServ { if next_flow_state.sys_state == FlowSysStateKind::Finish && !curr_inst.main { FlowLogServ::add_finish_log(&curr_inst, funs, ctx).await?; - FlowSearchClient::modify_business_obj_search(&curr_inst.rel_business_obj_id, &curr_inst.tag, funs, ctx).await?; + let rel_transition_names = Self::get_rel_transitions(&curr_inst.rel_business_obj_id, funs, ctx).await?.into_iter().map(|rel| rel.name).collect_vec(); + FlowSearchClient::modify_business_obj_search( + &curr_inst.rel_business_obj_id, + &curr_inst.tag, + json!({ + "rel_transitions": rel_transition_names, + }), + funs, + ctx, + ) + .await?; } Self::when_leave_state(&curr_inst, &prev_flow_state.id, &flow_model_version.rel_model_id, funs, ctx).await?; @@ -1229,7 +1276,7 @@ impl FlowInstServ { .iter() .filter(|model_transition| { model_transition.from_flow_state_id == flow_inst.current_state_id - && (spec_flow_transition_id.is_none() || &model_transition.id == spec_flow_transition_id.as_ref().unwrap()) + && (spec_flow_transition_id.is_none() || model_transition.id == spec_flow_transition_id.clone().unwrap_or_default()) }) .filter(|model_transition| { if skip_filter { @@ -1272,7 +1319,8 @@ impl FlowInstServ { .clone() .unwrap_or_default() .get("assigned_to") - .unwrap() + .cloned() + .unwrap_or(json!({})) .as_str() .unwrap_or_default() .split(',') @@ -1304,7 +1352,8 @@ impl FlowInstServ { if let Some(req_vars) = &req_vars { check_vars.extend(req_vars.clone()); } - if !BasicQueryCondInfo::check_or_and_conds(&guard_by_other_conds, &check_vars).unwrap() { + // 若 check_or_and_conds 报错,则表示条件配置有问题,忽略无效的配置直接给true + if !BasicQueryCondInfo::check_or_and_conds(&guard_by_other_conds, &check_vars).unwrap_or(true) { return false; } } @@ -1414,7 +1463,7 @@ impl FlowInstServ { update_time: Set(Some(Utc::now())), ..Default::default() }; - funs.db().update_one(flow_inst, ctx).await.unwrap(); + funs.db().update_one(flow_inst, ctx).await?; if flow_inst_detail.main { let curr_inst = Self::get(&flow_inst_detail.id, funs, ctx).await?; let ctx_cp = ctx.clone(); @@ -1425,7 +1474,7 @@ impl FlowInstServ { Ok(_) => {} Err(e) => error!("Flow Instance {} do_front_change error:{:?}", curr_inst.id, e), } - funs.commit().await.unwrap(); + funs.commit().await.unwrap_or_default(); }); } @@ -1433,35 +1482,13 @@ impl FlowInstServ { } async fn get_new_vars(tag: &str, rel_business_obj_id: String, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { - let tag_search_map = FlowSearchClient::get_tag_search_map(); - let new_vars = if let Some(mut search_resp) = FlowSearchClient::search( - &SearchItemSearchReq { - tag: tag_search_map.get(tag).ok_or_else(|| funs.err().not_found("flow_inst", "get_new_vars", "illegal response", "404-flow-tag-not-found"))?.clone(), - ctx: SearchItemSearchCtxReq::default(), - query: SearchItemQueryReq { - keys: Some(vec![rel_business_obj_id.into()]), - ..Default::default() - }, - adv_by_or: None, - adv_query: None, - sort: None, - page: SearchItemSearchPageReq { - number: 1, - size: 1, - fetch_total: false, - }, - }, - funs, - ctx, - ) - .await? - { - search_resp.records.pop().map(|item| item.ext) - } else { - None - } - .unwrap_or_default(); - Ok(TardisFuns::json.json_to_obj(new_vars).unwrap_or_default()) + let resp = FlowExternalServ::do_query_field(tag, vec![rel_business_obj_id], &ctx.own_paths, ctx, funs) + .await? + .objs + .pop() + .map(|val| TardisFuns::json.json_to_obj::>(val).unwrap_or_default()) + .unwrap_or_default(); + Ok(resp) } pub async fn find_var_by_inst_id(flow_inst: &FlowInstDetailResp, key: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { @@ -1542,19 +1569,10 @@ impl FlowInstServ { .await? .into_iter() .collect_vec(); - join_all( - insts - .iter() - .map(|inst| async { - Self::abort(&inst.id, &FlowInstAbortReq { - message: "".to_string() - }, funs, ctx).await - }) - .collect_vec(), - ) - .await - .into_iter() - .collect::>>()?; + join_all(insts.iter().map(|inst| async { Self::abort(&inst.id, &FlowInstAbortReq { message: "".to_string() }, funs, ctx).await }).collect_vec()) + .await + .into_iter() + .collect::>>()?; Ok(()) } @@ -1580,7 +1598,6 @@ impl FlowInstServ { own_paths: inst.own_paths.clone(), ..ctx.clone() }; - let global_ctx = TardisContext::default(); let flow_inst = flow_inst::ActiveModel { id: Set(inst.id.clone()), @@ -1589,52 +1606,65 @@ impl FlowInstServ { update_time: Set(Some(Utc::now())), ..Default::default() }; - funs.db().update_one(flow_inst, &mock_ctx).await.unwrap(); - let original_flow_state = FlowStateServ::get_item( - &inst.current_state_id, - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - ..Default::default() - }, - ..Default::default() - }, - funs, - &global_ctx, - ) - .await - .unwrap(); - let next_flow_state = FlowStateServ::get_item( - state_id, - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - ..Default::default() - }, - ..Default::default() - }, - funs, - &global_ctx, - ) - .await - .unwrap(); - - FlowExternalServ::do_notify_changes( - &inst.tag, - &inst.id, - &inst.rel_business_obj_id, - next_flow_state.name.clone(), - next_flow_state.sys_state, - original_flow_state.name.clone(), - original_flow_state.sys_state, - "UPDATE".to_string(), - false, - Some(false), - Some(FlowExternalCallbackOp::Auto), - ctx, - funs, - ) - .await + let result = funs.db().update_one(flow_inst, &mock_ctx).await; + + let inst_cp = inst.clone(); + let ctx_cp = ctx.clone(); + let state_id_cp = state_id.to_string(); + tardis::tokio::spawn(async move { + let global_ctx = TardisContext::default(); + let funs = flow_constants::get_tardis_inst(); + if let (Ok(original_flow_state), Ok(next_flow_state)) = ( + FlowStateServ::get_item( + &inst_cp.current_state_id, + &FlowStateFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + ..Default::default() + }, + ..Default::default() + }, + &funs, + &global_ctx, + ) + .await, + FlowStateServ::get_item( + &state_id_cp, + &FlowStateFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + ..Default::default() + }, + ..Default::default() + }, + &funs, + &global_ctx, + ) + .await, + ) { + let result = FlowExternalServ::do_notify_changes( + &inst_cp.tag, + &inst_cp.id, + &inst_cp.rel_business_obj_id, + next_flow_state.name.clone(), + next_flow_state.sys_state, + original_flow_state.name.clone(), + original_flow_state.sys_state, + "UPDATE".to_string(), + false, + Some(false), + Some(FlowExternalCallbackOp::Auto), + &ctx_cp, + &funs, + ) + .await; + match result { + Ok(_) => {} + Err(e) => error!("Flow Instance {} do_notify_changes error:{:?}", inst_cp.id, e), + } + } + }); + result }) .collect_vec(), ) @@ -1672,27 +1702,32 @@ impl FlowInstServ { .map(|tran| tran.next_flow_transition_id) .collect_vec(); let create_vars = flow_inst_detail.create_vars.clone().unwrap_or_default(); - let auto_transition = FlowTransitionServ::find_detail_items(transition_ids, None, None, funs, ctx).await?.into_iter().find(|transition| { - (transition.transfer_by_auto && transition.guard_by_other_conds().is_none()) - || (transition.transfer_by_auto - && transition.guard_by_other_conds().is_some() - && BasicQueryCondInfo::check_or_and_conds(&transition.guard_by_other_conds().unwrap(), &create_vars).unwrap()) - }); - if let Some(auto_transition) = auto_transition { - Self::transfer( - &flow_inst_detail, - &FlowInstTransferReq { - flow_transition_id: auto_transition.id, - message: None, - vars: None, - }, - false, - FlowExternalCallbackOp::Auto, - modified_instance_transations.clone(), - ctx, - funs, - ) - .await?; + let auto_transitions = + FlowTransitionServ::find_detail_items(transition_ids, None, None, funs, ctx).await?.into_iter().filter(|transition| transition.transfer_by_auto).collect_vec(); + if !auto_transitions.is_empty() { + if let Some(auto_transition) = auto_transitions.into_iter().find(|transition| { + (transition.transfer_by_auto && transition.guard_by_other_conds().is_none()) + || (transition.transfer_by_auto + && transition.guard_by_other_conds().is_some() + && BasicQueryCondInfo::check_or_and_conds(&transition.guard_by_other_conds().unwrap_or_default(), &create_vars).unwrap_or(true)) + }) { + Self::transfer( + &flow_inst_detail, + &FlowInstTransferReq { + flow_transition_id: auto_transition.id, + message: None, + vars: None, + }, + false, + FlowExternalCallbackOp::Auto, + modified_instance_transations.clone(), + ctx, + funs, + ) + .await?; + } else { + Self::abort(&flow_inst_detail.id, &FlowInstAbortReq { message: "".to_string() }, funs, ctx).await?; + } } Ok(()) @@ -1768,9 +1803,7 @@ impl FlowInstServ { if curr_operators.is_empty() && form_conf.auto_transfer_when_empty_kind.is_some() { match form_conf.auto_transfer_when_empty_kind.unwrap_or_default() { FlowStatusAutoStrategyKind::Autoskip => { - if let Some(next_transition) = - FlowInstServ::find_next_transitions(flow_inst_detail, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() - { + if let Some(next_transition) = Self::find_next_transitions(flow_inst_detail, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { FlowLogServ::add_operate_log( &FlowInstOperateReq { operate: FlowStateOperatorKind::Submit, @@ -1867,9 +1900,7 @@ impl FlowInstServ { if curr_approval_total == 0 && approval_conf.auto_transfer_when_empty_kind.is_some() { match approval_conf.auto_transfer_when_empty_kind.unwrap_or_default() { FlowStatusAutoStrategyKind::Autoskip => { - if let Some(next_transition) = - FlowInstServ::find_next_transitions(flow_inst_detail, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() - { + if let Some(next_transition) = Self::find_next_transitions(flow_inst_detail, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { FlowLogServ::add_operate_log( &FlowInstOperateReq { operate: FlowStateOperatorKind::Pass, @@ -2106,7 +2137,7 @@ impl FlowInstServ { FlowStateKind::Form => kind_conf.form.as_ref().map(|form| { let mut operators = HashMap::new(); let artifacts = artifacts.clone().unwrap_or_default(); - if !finish + if !finish && artifacts.curr_operators.clone().unwrap_or_default().contains(&ctx.owner) && !artifacts.prohibit_guard_by_spec_account_ids.clone().unwrap_or_default().contains(&ctx.owner) { @@ -2262,7 +2293,7 @@ impl FlowInstServ { ctx, ) .await?; - if let Some(next_transition) = FlowInstServ::find_next_transitions(inst, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { + if let Some(next_transition) = Self::find_next_transitions(inst, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { Self::transfer( inst, &FlowInstTransferReq { @@ -2326,7 +2357,7 @@ impl FlowInstServ { .await?; let curr_inst = Self::get(&inst.id, funs, ctx).await?; if Self::check_approval_cond(&curr_inst, FlowApprovalResultKind::Pass, funs, ctx).await? { - if let Some(next_transition) = FlowInstServ::find_next_transitions(inst, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { + if let Some(next_transition) = Self::find_next_transitions(inst, &FlowInstFindNextTransitionsReq { vars: None }, funs, ctx).await?.pop() { FlowLogServ::add_operate_log( operate_req, inst, @@ -2340,7 +2371,7 @@ impl FlowInstServ { ) .await?; let mut prev_non_auto_state_id = artifacts.prev_non_auto_state_id.unwrap_or_default(); - prev_non_auto_state_id.push(inst.current_state_id.clone()); + prev_non_auto_state_id.push(inst.current_state_id.clone()); Self::modify_inst_artifacts( &inst.id, &FlowInstArtifactsModifyReq { @@ -2880,4 +2911,124 @@ impl FlowInstServ { vars_collect } + + pub async fn get_rel_transitions(rel_business_obj_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { + let mut result = vec![]; + let rel_version_ids = Self::find_detail_items( + &FlowInstFilterReq { + rel_business_obj_ids: Some(vec![rel_business_obj_id.to_string()]), + main: Some(false), + finish: Some(false), + ..Default::default() + }, + funs, + ctx, + ) + .await? + .into_iter() + .map(|inst| inst.rel_flow_version_id) + .collect_vec(); + for rel_version_id in rel_version_ids { + if let Some(rel_model_id) = FlowModelVersionServ::find_one_item( + &FlowModelVersionFilterReq { + basic: RbumBasicFilterReq { + ids: Some(vec![rel_version_id]), + with_sub_own_paths: true, + own_paths: Some("".to_string()), + ..Default::default() + }, + ..Default::default() + }, + funs, + ctx, + ) + .await? + .map(|version| version.rel_model_id) + { + let rel_transition_ext = FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTransition, &rel_model_id, None, None, funs, ctx) + .await? + .pop() + .map(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default()); + if let Some(ext) = rel_transition_ext { + result.push(ext); + } + } + } + Ok(result) + } + + pub async fn sync_status(funs: &TardisFunsInst) -> TardisResult<()> { + #[derive(sea_orm::FromQueryResult)] + pub struct FlowInstResult { + rel_business_obj_id: String, + tag: String, + own_paths: String, + current_state_name: Option, + } + let mut page_num = 1; + let page_size = 5000; + + loop { + let flow_insts = funs + .db() + .paginate_dtos::( + Query::select() + .columns([ + (flow_inst::Entity, flow_inst::Column::Id), + (flow_inst::Entity, flow_inst::Column::RelBusinessObjId), + (flow_inst::Entity, flow_inst::Column::Tag), + (flow_inst::Entity, flow_inst::Column::OwnPaths), + ]) + .expr_as(Expr::col((RBUM_ITEM_TABLE.clone(), NAME_FIELD.clone())).if_null(""), Alias::new("current_state_name")) + .from(flow_inst::Entity) + .left_join( + RBUM_ITEM_TABLE.clone(), + Cond::all() + .add(Expr::col((RBUM_ITEM_TABLE.clone(), ID_FIELD.clone())).equals((flow_inst::Entity, flow_inst::Column::CurrentStateId))) + .add(Expr::col((RBUM_ITEM_TABLE.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap_or_default())) + .add(Expr::col((RBUM_ITEM_TABLE.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap_or_default())), + ) + .and_where(Expr::col(flow_inst::Column::Main).eq(true)) + .order_by((flow_inst::Entity, flow_inst::Column::CreateTime), Order::Desc), + page_num, + page_size, + ) + .await? + .0; + if flow_insts.is_empty() { + break; + } + join_all( + flow_insts + .iter() + .map(|flow_inst| async { + if let Some(current_state_name) = &flow_inst.current_state_name { + let ctx = TardisContext { + own_paths: flow_inst.own_paths.clone(), + ..Default::default() + }; + FlowSearchClient::modify_business_obj_search( + &flow_inst.rel_business_obj_id, + &flow_inst.tag, + json!({ + "status": current_state_name, + }), + funs, + &ctx, + ) + .await + } else { + Ok(()) + } + }) + .collect_vec(), + ) + .await; + + page_num += 1; + } + + // + Ok(()) + } } diff --git a/backend/middlewares/flow/src/serv/flow_log_serv.rs b/backend/middlewares/flow/src/serv/flow_log_serv.rs index afcbaa6bc..ac03ae4e6 100644 --- a/backend/middlewares/flow/src/serv/flow_log_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_log_serv.rs @@ -3,7 +3,8 @@ use std::collections::HashMap; use bios_basic::rbum::{dto::rbum_filer_dto::RbumBasicFilterReq, helper::rbum_scope_helper, rbum_enumeration::RbumScopeLevelKind, serv::rbum_item_serv::RbumItemCrudOperation}; use serde_json::Value; use tardis::{ - basic::{dto::TardisContext, result::TardisResult}, web::poem_openapi::types::Type, TardisFuns, TardisFunsInst + basic::{dto::TardisContext, result::TardisResult}, + TardisFuns, TardisFunsInst, }; use crate::dto::{ @@ -182,7 +183,7 @@ impl FlowLogServ { "__DELETE__" => "删除审批".to_string(), _ => format!("{}({})", rel_transition.name, rel_transition.from_flow_state_name).to_string(), }; - let mut log_ext = LogParamExt { + let log_ext = LogParamExt { scene_kind: Some(vec![String::from(LogParamExtSceneKind::Detail)]), new_log: Some(true), project_id: rbum_scope_helper::get_path_item(RbumScopeLevelKind::L2.to_int(), &ctx.own_paths), @@ -480,7 +481,7 @@ impl FlowLogServ { new_content: None, ..Default::default() }; - + if !artifacts.his_operators.as_ref().unwrap_or(&vec![]).contains(&ctx.owner) && !artifacts.curr_operators.as_ref().unwrap_or(&vec![]).contains(&ctx.owner) { log_content.sub_id = None; } diff --git a/backend/middlewares/flow/src/serv/flow_model_serv.rs b/backend/middlewares/flow/src/serv/flow_model_serv.rs index 7013593c7..28531b4e6 100644 --- a/backend/middlewares/flow/src/serv/flow_model_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_model_serv.rs @@ -17,6 +17,7 @@ use tardis::{ EntityName, Set, }, futures::future::join_all, + log::error, serde_json::json, tokio, web::web_resp::TardisPage, @@ -556,32 +557,34 @@ impl RbumItemCrudOperation, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - if detail.is_some() && detail.as_ref().unwrap().template && detail.as_ref().unwrap().rel_model_id.is_empty() { - FlowSearchClient::async_delete_model_search(flow_model_id.to_string(), funs, ctx).await?; - FlowLogClient::add_ctx_task( - LogParamTag::DynamicLog, - Some(flow_model_id.to_string()), - LogParamContent { - subject: Some("工作流模板".to_string()), - name: Some(detail.as_ref().unwrap().name.clone()), - sub_kind: Some("flow_template".to_string()), - ..Default::default() - }, - Some(json!({ - "name": detail.as_ref().unwrap().name.to_string(), - "info": detail.as_ref().unwrap().info.clone(), - "rel_template_ids":detail.as_ref().unwrap().rel_template_ids.clone(), - "scope_level": detail.as_ref().unwrap().scope_level.clone(), - "tag": detail.as_ref().unwrap().tag.clone(), - })), - Some("dynamic_log_tenant_config".to_string()), - Some("删除".to_string()), - rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.own_paths), - true, - ctx, - false, - ) - .await?; + if let Some(detail) = detail { + if detail.template && detail.rel_model_id.is_empty() { + FlowSearchClient::async_delete_model_search(flow_model_id.to_string(), funs, ctx).await?; + FlowLogClient::add_ctx_task( + LogParamTag::DynamicLog, + Some(flow_model_id.to_string()), + LogParamContent { + subject: Some("工作流模板".to_string()), + name: Some(detail.name.clone()), + sub_kind: Some("flow_template".to_string()), + ..Default::default() + }, + Some(json!({ + "name": detail.name.to_string(), + "info": detail.info.clone(), + "rel_template_ids":detail.rel_template_ids.clone(), + "scope_level": detail.scope_level.clone(), + "tag": detail.tag.clone(), + })), + Some("dynamic_log_tenant_config".to_string()), + Some("删除".to_string()), + rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.own_paths), + true, + ctx, + false, + ) + .await?; + } } Ok(()) } @@ -1058,22 +1061,31 @@ impl FlowModelServ { rel_model.scope_level = rbum_scope_helper::get_scope_level_by_context(ctx)?; let mut rel_transition = rel_model.rel_transition().unwrap_or_default(); if !rel_transition.id.is_empty() && (rel_transition.id != *"__EDIT__" || rel_transition.id != *"__DETELE__") { - if let Some(rel_main_model_tran) = FlowModelServ::find_one_detail_item(&FlowModelFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, + if let Some(rel_main_model_tran) = FlowModelServ::find_one_detail_item( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ignore_scope: true, + ..Default::default() + }, + tags: Some(vec![rel_model.tag.clone()]), + main: Some(true), ..Default::default() }, - tags: Some(vec![rel_model.tag.clone()]), - main: Some(true), - ..Default::default() - }, funs, ctx).await?.map(|model| - model.transitions().into_iter() - .find(|tran| tran.from_flow_state_name == rel_transition.from_flow_state_name && Some(tran.to_flow_state_name.clone()) == rel_transition.to_flow_state_name) - ).unwrap_or(None) { + funs, + ctx, + ) + .await? + .map(|model| { + model.transitions().into_iter().find(|tran| { + tran.from_flow_state_name == rel_transition.from_flow_state_name && Some(tran.to_flow_state_name.clone()) == rel_transition.to_flow_state_name + }) + }) + .unwrap_or(None) + { rel_transition.id = rel_main_model_tran.id; rel_model.rel_transition = Some(json!(rel_transition)); } - } + } } Self::add_item( &mut FlowModelAddReq { @@ -1201,23 +1213,17 @@ impl FlowModelServ { ctx, ) .await?; - Self::modify_model(&added_model.id, &mut FlowModelModifyReq { - rel_model_id: Some(from_model.rel_model_id.clone()), - ..Default::default() - }, funs, ctx).await?; - FlowRelServ::add_simple_rel( - &FlowRelKind::FlowModelTemplate, + Self::modify_model( &added_model.id, - to_template_id, - None, - None, - false, - true, - None, + &mut FlowModelModifyReq { + rel_model_id: Some(from_model.rel_model_id.clone()), + ..Default::default() + }, funs, ctx, ) .await?; + FlowRelServ::add_simple_rel(&FlowRelKind::FlowModelTemplate, &added_model.id, to_template_id, None, None, false, true, None, funs, ctx).await?; result.insert(from_model.rel_model_id.clone(), added_model); } Ok(result) @@ -1665,7 +1671,7 @@ impl FlowModelServ { .map(|model| async move { let funs = flow_constants::get_tardis_inst(); let global_ctx: TardisContext = TardisContext::default(); - if FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTemplate, &model.id, None, None, &funs, &global_ctx).await.unwrap().is_empty() { + if FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTemplate, &model.id, None, None, &funs, &global_ctx).await.unwrap_or_default().is_empty() { Some(model) } else { None @@ -1857,32 +1863,34 @@ impl FlowModelServ { } if let Some(ref mut modify_transitions) = &mut bind_state.modify_transitions { for modify_transition in modify_transitions.iter_mut() { - let parent_model_transition = parent_model_transitions.iter().find(|trans| trans.id == modify_transition.id.to_string()).unwrap(); - modify_transition.id = child_model_transitions - .iter() - .find(|child_tran| { - child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id - && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id - }) - .map(|trans| trans.id.clone()) - .unwrap_or_default() - .into(); - } - } - if let Some(delete_transitions) = &mut bind_state.delete_transitions { - let mut child_delete_transitions = vec![]; - for delete_transition_id in delete_transitions.iter_mut() { - let parent_model_transition = parent_model_transitions.iter().find(|trans| trans.id == delete_transition_id.clone()).unwrap(); - child_delete_transitions.push( - child_model_transitions + if let Some(parent_model_transition) = parent_model_transitions.iter().find(|trans| trans.id == modify_transition.id.to_string()) { + modify_transition.id = child_model_transitions .iter() .find(|child_tran| { - child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id + child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id }) .map(|trans| trans.id.clone()) - .unwrap_or_default(), - ); + .unwrap_or_default() + .into(); + } + } + } + if let Some(delete_transitions) = &mut bind_state.delete_transitions { + let mut child_delete_transitions = vec![]; + for delete_transition_id in delete_transitions.iter_mut() { + if let Some(parent_model_transition) = parent_model_transitions.iter().find(|trans| trans.id == delete_transition_id.clone()) { + child_delete_transitions.push( + child_model_transitions + .iter() + .find(|child_tran| { + child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id + && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id + }) + .map(|trans| trans.id.clone()) + .unwrap_or_default(), + ); + } } bind_state.delete_transitions = Some(child_delete_transitions); } @@ -1902,32 +1910,34 @@ impl FlowModelServ { } if let Some(ref mut modify_transitions) = &mut modify_state.modify_transitions { for modify_transition in modify_transitions.iter_mut() { - let parent_model_transition = parent_model_transitions.iter().find(|trans| trans.id == modify_transition.id.to_string()).unwrap(); - modify_transition.id = child_model_transitions - .iter() - .find(|child_tran| { - child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id - && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id - }) - .map(|trans| trans.id.clone()) - .unwrap_or_default() - .into(); - } - } - if let Some(delete_transitions) = &mut modify_state.delete_transitions { - let mut child_delete_transitions = vec![]; - for delete_transition_id in delete_transitions.iter_mut() { - let parent_model_transition = parent_model_transitions.iter().find(|trans| trans.id == delete_transition_id.clone()).unwrap(); - child_delete_transitions.push( - child_model_transitions + if let Some(parent_model_transition) = parent_model_transitions.iter().find(|trans| trans.id == modify_transition.id.to_string()) { + modify_transition.id = child_model_transitions .iter() .find(|child_tran| { - child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id + child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id }) .map(|trans| trans.id.clone()) - .unwrap_or_default(), - ); + .unwrap_or_default() + .into(); + } + } + } + if let Some(delete_transitions) = &mut modify_state.delete_transitions { + let mut child_delete_transitions = vec![]; + for delete_transition_id in delete_transitions.iter_mut() { + if let Some(parent_model_transition) = parent_model_transitions.iter().find(|trans| trans.id == delete_transition_id.clone()) { + child_delete_transitions.push( + child_model_transitions + .iter() + .find(|child_tran| { + child_tran.from_flow_state_id == parent_model_transition.from_flow_state_id + && child_tran.to_flow_state_id == parent_model_transition.to_flow_state_id + }) + .map(|trans| trans.id.clone()) + .unwrap_or_default(), + ); + } } modify_state.delete_transitions = Some(child_delete_transitions); } @@ -1938,11 +1948,15 @@ impl FlowModelServ { let child_model_clone = child_model.clone(); ctx.add_async_task(Box::new(|| { Box::pin(async move { + let child_model_id = child_model_clone.id.clone(); let task_handle = tokio::spawn(async move { let funs = flow_constants::get_tardis_inst(); - let _ = Self::modify_item(&child_model_clone.id, &mut modify_req_clone, &funs, &ctx_clone).await; + let _ = Self::modify_item(&child_model_id, &mut modify_req_clone, &funs, &ctx_clone).await; }); - task_handle.await.unwrap(); + match task_handle.await { + Ok(_) => {} + Err(e) => error!("Flow Model {} sync_child_model error:{:?}", child_model_clone.id, e), + } Ok(()) }) })) @@ -1965,9 +1979,10 @@ impl FlowModelServ { let mut modify_states = HashMap::new(); let transitions = FlowTransitionServ::find_transitions(&model_detail.current_version_id, None, funs, ctx).await?; for modify_tran in modify_trans { - let tansition = transitions.iter().find(|tran| tran.id == modify_tran.id.to_string()).unwrap(); - let modify_transitons = modify_states.entry(&tansition.from_flow_state_id).or_insert(vec![]); - modify_transitons.push(modify_tran); + if let Some(tansition) = transitions.iter().find(|tran| tran.id == modify_tran.id.to_string()) { + let modify_transitons = modify_states.entry(&tansition.from_flow_state_id).or_insert(vec![]); + modify_transitons.push(modify_tran); + } } FlowModelServ::modify_model( flow_model_id, diff --git a/backend/middlewares/flow/src/serv/flow_model_version_serv.rs b/backend/middlewares/flow/src/serv/flow_model_version_serv.rs index 4f3344594..ef3225d50 100644 --- a/backend/middlewares/flow/src/serv/flow_model_version_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_model_version_serv.rs @@ -437,7 +437,7 @@ impl FlowModelVersionServ { } pub async fn delete_state(flow_version_id: &str, state_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let state = FlowStateServ::find_one_detail_item( + let _state = FlowStateServ::find_one_detail_item( &FlowStateFilterReq { basic: RbumBasicFilterReq { ids: Some(vec![state_id.to_string()]), @@ -495,11 +495,13 @@ impl FlowModelVersionServ { ) .await .unwrap_or_default() - .unwrap() }) .collect::>(), ) - .await) + .await + .into_iter() + .flatten() + .collect_vec()) } pub async fn create_editing_version(flow_version_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { diff --git a/backend/middlewares/flow/src/serv/flow_transition_serv.rs b/backend/middlewares/flow/src/serv/flow_transition_serv.rs index 553490513..065c34d4c 100644 --- a/backend/middlewares/flow/src/serv/flow_transition_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_transition_serv.rs @@ -23,7 +23,9 @@ use tardis::{ use crate::{ domain::{flow_state, flow_transition}, dto::{ - flow_model_dto::{FlowModelFilterReq, FlowModelStatus}, flow_state_dto::{FlowStateFilterReq, FlowStateKind}, flow_transition_dto::{FlowTransitionActionChangeKind, FlowTransitionAddReq, FlowTransitionDetailResp, FlowTransitionFilterReq, FlowTransitionModifyReq} + flow_model_dto::{FlowModelFilterReq, FlowModelStatus}, + flow_state_dto::{FlowStateFilterReq, FlowStateKind}, + flow_transition_dto::{FlowTransitionActionChangeKind, FlowTransitionAddReq, FlowTransitionDetailResp, FlowTransitionFilterReq, FlowTransitionModifyReq}, }, }; @@ -89,7 +91,7 @@ impl FlowTransitionServ { guard_by_spec_account_ids: Set(req.guard_by_spec_account_ids.as_ref().unwrap_or(&vec![]).clone()), guard_by_spec_role_ids: Set(req.guard_by_spec_role_ids.as_ref().unwrap_or(&vec![]).clone()), guard_by_spec_org_ids: Set(req.guard_by_spec_org_ids.as_ref().unwrap_or(&vec![]).clone()), - guard_by_other_conds: Set(req.guard_by_other_conds.as_ref().map(|conds| TardisFuns::json.obj_to_json(conds).unwrap()).unwrap_or(json!([]))), + guard_by_other_conds: Set(req.guard_by_other_conds.as_ref().map(|conds| TardisFuns::json.obj_to_json(conds).unwrap_or(json!([]))).unwrap_or(json!([]))), vars_collect: Set(req.vars_collect.clone().unwrap_or_default()), double_check: Set(req.double_check.clone().unwrap_or_default()), @@ -112,8 +114,8 @@ impl FlowTransitionServ { let flow_state_ids = modify_req .iter() .filter(|req| req.from_flow_state_id.is_some()) - .map(|req| req.from_flow_state_id.as_ref().unwrap().to_string()) - .chain(modify_req.iter().filter(|req| req.to_flow_state_id.is_some()).map(|req| req.to_flow_state_id.as_ref().unwrap().to_string())) + .map(|req| req.from_flow_state_id.clone().unwrap_or_default()) + .chain(modify_req.iter().filter(|req| req.to_flow_state_id.is_some()).map(|req| req.to_flow_state_id.clone().unwrap_or_default())) .unique() .collect_vec(); if modify_req.iter().any(|req| { @@ -160,110 +162,106 @@ impl FlowTransitionServ { } let model_transitions = Self::find_transitions(flow_version_id, None, funs, ctx).await?; for req in modify_req { - let transiton = model_transitions.iter().find(|trans| trans.id == req.id.to_string()); - if transiton.is_none() { - continue; - } - - let mut flow_transition = flow_transition::ActiveModel { - id: Set(req.id.to_string()), - ..Default::default() - }; - if let Some(name) = &req.name { - flow_transition.name = Set(name.to_string()); - } - if let Some(from_flow_state_id) = &req.from_flow_state_id { - // @TODO 替前端处理 - let from_state = FlowStateServ::get_item( - from_flow_state_id, - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - own_paths: Some("".to_string()), + if let Some(transiton) = model_transitions.iter().find(|trans| trans.id == req.id.to_string()) { + let mut flow_transition = flow_transition::ActiveModel { + id: Set(req.id.to_string()), + ..Default::default() + }; + if let Some(name) = &req.name { + flow_transition.name = Set(name.to_string()); + } + if let Some(from_flow_state_id) = &req.from_flow_state_id { + // @TODO 替前端处理 + let from_state = FlowStateServ::get_item( + from_flow_state_id, + &FlowStateFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + own_paths: Some("".to_string()), + ..Default::default() + }, ..Default::default() }, - ..Default::default() - }, - funs, - ctx, - ) - .await?; - flow_transition.from_flow_state_id = Set(from_flow_state_id.to_string()); - flow_transition.transfer_by_auto = Set(from_state.state_kind == FlowStateKind::Start || from_state.state_kind == FlowStateKind::Branch); - } - if let Some(to_flow_state_id) = &req.to_flow_state_id { - flow_transition.to_flow_state_id = Set(to_flow_state_id.to_string()); - } + funs, + ctx, + ) + .await?; + flow_transition.from_flow_state_id = Set(from_flow_state_id.to_string()); + flow_transition.transfer_by_auto = Set(from_state.state_kind == FlowStateKind::Start || from_state.state_kind == FlowStateKind::Branch); + } + if let Some(to_flow_state_id) = &req.to_flow_state_id { + flow_transition.to_flow_state_id = Set(to_flow_state_id.to_string()); + } - if let Some(transfer_by_auto) = req.transfer_by_auto { - flow_transition.transfer_by_auto = Set(transfer_by_auto); - } - if let Some(transfer_by_timer) = &req.transfer_by_timer { - flow_transition.transfer_by_timer = Set(transfer_by_timer.to_string()); - } + if let Some(transfer_by_auto) = req.transfer_by_auto { + flow_transition.transfer_by_auto = Set(transfer_by_auto); + } + if let Some(transfer_by_timer) = &req.transfer_by_timer { + flow_transition.transfer_by_timer = Set(transfer_by_timer.to_string()); + } - if let Some(guard_by_creator) = req.guard_by_creator { - flow_transition.guard_by_creator = Set(guard_by_creator); - } - if let Some(guard_by_his_operators) = req.guard_by_his_operators { - flow_transition.guard_by_his_operators = Set(guard_by_his_operators); - } - if let Some(guard_by_assigned) = req.guard_by_assigned { - flow_transition.guard_by_assigned = Set(guard_by_assigned); - } - if let Some(guard_by_spec_account_ids) = &req.guard_by_spec_account_ids { - flow_transition.guard_by_spec_account_ids = Set(guard_by_spec_account_ids.clone()); - } - if let Some(guard_by_spec_role_ids) = &req.guard_by_spec_role_ids { - flow_transition.guard_by_spec_role_ids = Set(guard_by_spec_role_ids.clone()); - } - if let Some(guard_by_spec_org_ids) = &req.guard_by_spec_org_ids { - flow_transition.guard_by_spec_org_ids = Set(guard_by_spec_org_ids.clone()); - } - if let Some(guard_by_other_conds) = &req.guard_by_other_conds { - flow_transition.guard_by_other_conds = Set(TardisFuns::json.obj_to_json(guard_by_other_conds)?); - } + if let Some(guard_by_creator) = req.guard_by_creator { + flow_transition.guard_by_creator = Set(guard_by_creator); + } + if let Some(guard_by_his_operators) = req.guard_by_his_operators { + flow_transition.guard_by_his_operators = Set(guard_by_his_operators); + } + if let Some(guard_by_assigned) = req.guard_by_assigned { + flow_transition.guard_by_assigned = Set(guard_by_assigned); + } + if let Some(guard_by_spec_account_ids) = &req.guard_by_spec_account_ids { + flow_transition.guard_by_spec_account_ids = Set(guard_by_spec_account_ids.clone()); + } + if let Some(guard_by_spec_role_ids) = &req.guard_by_spec_role_ids { + flow_transition.guard_by_spec_role_ids = Set(guard_by_spec_role_ids.clone()); + } + if let Some(guard_by_spec_org_ids) = &req.guard_by_spec_org_ids { + flow_transition.guard_by_spec_org_ids = Set(guard_by_spec_org_ids.clone()); + } + if let Some(guard_by_other_conds) = &req.guard_by_other_conds { + flow_transition.guard_by_other_conds = Set(TardisFuns::json.obj_to_json(guard_by_other_conds)?); + } - if let Some(vars_collect) = &req.vars_collect { - flow_transition.vars_collect = Set(vars_collect.clone()); - } + if let Some(vars_collect) = &req.vars_collect { + flow_transition.vars_collect = Set(vars_collect.clone()); + } - if let Some(action_by_pre_callback) = &req.action_by_pre_callback { - flow_transition.action_by_pre_callback = Set(action_by_pre_callback.to_string()); - } - if let Some(action_by_post_callback) = &req.action_by_post_callback { - flow_transition.action_by_post_callback = Set(action_by_post_callback.to_string()); - } - if let Some(action_by_front_changes) = &req.action_by_front_changes { - flow_transition.action_by_front_changes = Set(action_by_front_changes.clone()); - } - if let Some(action_by_post_changes) = &req.action_by_post_changes { - flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); - } - if let Some(action_by_post_var_changes) = &req.action_by_post_var_changes { - let mut state_post_changes = - transiton.unwrap().action_by_post_changes().into_iter().filter(|post| post.kind == FlowTransitionActionChangeKind::State).collect_vec(); - let mut action_by_post_changes = action_by_post_var_changes.clone(); - action_by_post_changes.append(&mut state_post_changes); - flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); - } - if let Some(action_by_post_state_changes) = &req.action_by_post_state_changes { - let mut var_post_changes = transiton.unwrap().action_by_post_changes().into_iter().filter(|post| post.kind == FlowTransitionActionChangeKind::Var).collect_vec(); - let mut action_by_post_changes = action_by_post_state_changes.clone(); - action_by_post_changes.append(&mut var_post_changes); - flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); - } - if let Some(double_check) = &req.double_check { - flow_transition.double_check = Set(double_check.clone()); - } - if let Some(is_notify) = &req.is_notify { - flow_transition.is_notify = Set(*is_notify); - } - if let Some(sort) = &req.sort { - flow_transition.sort = Set(*sort); + if let Some(action_by_pre_callback) = &req.action_by_pre_callback { + flow_transition.action_by_pre_callback = Set(action_by_pre_callback.to_string()); + } + if let Some(action_by_post_callback) = &req.action_by_post_callback { + flow_transition.action_by_post_callback = Set(action_by_post_callback.to_string()); + } + if let Some(action_by_front_changes) = &req.action_by_front_changes { + flow_transition.action_by_front_changes = Set(action_by_front_changes.clone()); + } + if let Some(action_by_post_changes) = &req.action_by_post_changes { + flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); + } + if let Some(action_by_post_var_changes) = &req.action_by_post_var_changes { + let mut state_post_changes = transiton.action_by_post_changes().into_iter().filter(|post| post.kind == FlowTransitionActionChangeKind::State).collect_vec(); + let mut action_by_post_changes = action_by_post_var_changes.clone(); + action_by_post_changes.append(&mut state_post_changes); + flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); + } + if let Some(action_by_post_state_changes) = &req.action_by_post_state_changes { + let mut var_post_changes = transiton.action_by_post_changes().into_iter().filter(|post| post.kind == FlowTransitionActionChangeKind::Var).collect_vec(); + let mut action_by_post_changes = action_by_post_state_changes.clone(); + action_by_post_changes.append(&mut var_post_changes); + flow_transition.action_by_post_changes = Set(action_by_post_changes.clone()); + } + if let Some(double_check) = &req.double_check { + flow_transition.double_check = Set(double_check.clone()); + } + if let Some(is_notify) = &req.is_notify { + flow_transition.is_notify = Set(*is_notify); + } + if let Some(sort) = &req.sort { + flow_transition.sort = Set(*sort); + } + flow_transition.update_time = Set(Utc::now()); + funs.db().update_one(flow_transition, ctx).await?; } - flow_transition.update_time = Set(Utc::now()); - funs.db().update_one(flow_transition, ctx).await?; } Ok(()) } @@ -342,8 +340,8 @@ impl FlowTransitionServ { from_state_rbum_table.clone(), Cond::all() .add(Expr::col((from_state_rbum_table.clone(), ID_FIELD.clone())).equals((flow_transition::Entity, flow_transition::Column::FromFlowStateId))) - .add(Expr::col((from_state_rbum_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap())) - .add(Expr::col((from_state_rbum_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap())), + .add(Expr::col((from_state_rbum_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap_or_default())) + .add(Expr::col((from_state_rbum_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap_or_default())), ) .join_as( JoinType::LeftJoin, @@ -357,8 +355,8 @@ impl FlowTransitionServ { to_state_rbum_table.clone(), Cond::all() .add(Expr::col((to_state_rbum_table.clone(), ID_FIELD.clone())).equals((flow_transition::Entity, flow_transition::Column::ToFlowStateId))) - .add(Expr::col((to_state_rbum_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap())) - .add(Expr::col((to_state_rbum_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap())), + .add(Expr::col((to_state_rbum_table.clone(), REL_KIND_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_kind_id().unwrap_or_default())) + .add(Expr::col((to_state_rbum_table.clone(), REL_DOMAIN_ID_FIELD.clone())).eq(FlowStateServ::get_rbum_domain_id().unwrap_or_default())), ) .join_as( JoinType::LeftJoin, diff --git a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs index 5dd8826b2..7bb338638 100644 --- a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs +++ b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs @@ -268,7 +268,7 @@ pub async fn test(flow_client: &mut TestHttpClient, search_client: &mut TestHttp ) .await; let req_model_uninit_template_id = req_model_uninit_template_aggs.id.clone(); - sleep(Duration::from_millis(1000)).await; + sleep(Duration::from_millis(5000)).await; let model_templates: TardisPage = search_client .put( "/ci/item/search", @@ -290,10 +290,10 @@ pub async fn test(flow_client: &mut TestHttpClient, search_client: &mut TestHttp }, ) .await; - // assert_eq!(model_templates.total_size, 3); - // assert!(model_templates.records.iter().any(|record| record.key == req_default_model_template_id)); - // assert!(model_templates.records.iter().any(|record| record.key == req_model_uninit_template_id)); - // assert!(model_templates.records.iter().any(|record| record.key == req_model_template_id)); + assert_eq!(model_templates.total_size, 3); + assert!(model_templates.records.iter().any(|record| record.key == req_default_model_template_id)); + assert!(model_templates.records.iter().any(|record| record.key == req_model_uninit_template_id)); + assert!(model_templates.records.iter().any(|record| record.key == req_model_template_id)); // template bind model let mut rel_model_ids = HashMap::new(); rel_model_ids.insert("REQ".to_string(), req_model_template_id.clone()); diff --git a/backend/supports/auth/src/error.rs b/backend/supports/auth/src/error.rs index 30a6d4933..f412c821d 100644 --- a/backend/supports/auth/src/error.rs +++ b/backend/supports/auth/src/error.rs @@ -8,4 +8,3 @@ pub trait AuthError { } impl AuthError for TardisError {} - diff --git a/backend/supports/auth/src/lib.rs b/backend/supports/auth/src/lib.rs index 81a25ee31..a27a4829a 100644 --- a/backend/supports/auth/src/lib.rs +++ b/backend/supports/auth/src/lib.rs @@ -5,6 +5,6 @@ pub mod auth_config; pub mod auth_constants; pub mod auth_initializer; pub mod dto; +mod error; pub mod helper; pub mod serv; -mod error; diff --git a/backend/supports/auth/src/serv/auth_crypto_serv.rs b/backend/supports/auth/src/serv/auth_crypto_serv.rs index 7aef9e2d1..9306db06c 100644 --- a/backend/supports/auth/src/serv/auth_crypto_serv.rs +++ b/backend/supports/auth/src/serv/auth_crypto_serv.rs @@ -13,7 +13,8 @@ use lazy_static::lazy_static; use crate::{ auth_config::AuthConfig, auth_constants::DOMAIN_CODE, - dto::auth_crypto_dto::{AuthEncryptReq, AuthEncryptResp}, error::AuthError, + dto::auth_crypto_dto::{AuthEncryptReq, AuthEncryptResp}, + error::AuthError, }; lazy_static! { diff --git a/backend/supports/iam/src/console_system/api/iam_cs_role_api.rs b/backend/supports/iam/src/console_system/api/iam_cs_role_api.rs index 8cbf4e934..1d47dcd6f 100644 --- a/backend/supports/iam/src/console_system/api/iam_cs_role_api.rs +++ b/backend/supports/iam/src/console_system/api/iam_cs_role_api.rs @@ -362,4 +362,4 @@ impl IamCsRoleApi { TardisResp::ok(Void {}) } -} \ No newline at end of file +} diff --git a/backend/supports/iam/src/iam_config.rs b/backend/supports/iam/src/iam_config.rs index 539e88eca..c5da9d0bc 100644 --- a/backend/supports/iam/src/iam_config.rs +++ b/backend/supports/iam/src/iam_config.rs @@ -11,7 +11,7 @@ use tardis::TardisFunsInst; use bios_basic::rbum::rbum_config::RbumConfig; use tardis::web::poem::http::HeaderName; - + #[derive(Debug, Serialize, Deserialize, Clone)] #[serde(default)] pub struct IamConfig { diff --git a/frontend/clients/hwsms/src/ext/reach.rs b/frontend/clients/hwsms/src/ext/reach.rs index 48eca571a..a168a58c1 100644 --- a/frontend/clients/hwsms/src/ext/reach.rs +++ b/frontend/clients/hwsms/src/ext/reach.rs @@ -32,7 +32,6 @@ impl SendChannel for crate::SmsClient { // replace . with full-width dot for censorship *s = s.replace('.', "."); } - } let template_paras = content_as_json_string_array.iter().map(|s| s.as_str()).collect(); tardis::log::trace!("send sms {content}"); diff --git a/frontend/sdks/invoke/src/clients.rs b/frontend/sdks/invoke/src/clients.rs index fd3778624..954ff000b 100644 --- a/frontend/sdks/invoke/src/clients.rs +++ b/frontend/sdks/invoke/src/clients.rs @@ -31,10 +31,10 @@ pub mod iam_client; pub mod event_client; pub mod flow_client; -#[cfg(feature = "schedule")] -pub mod schedule_client; #[cfg(feature = "reach")] pub mod reach_client; +#[cfg(feature = "schedule")] +pub mod schedule_client; #[macro_export] /// diff --git a/frontend/sdks/invoke/src/clients/reach_client.rs b/frontend/sdks/invoke/src/clients/reach_client.rs index e38c8bfb6..5c0696373 100644 --- a/frontend/sdks/invoke/src/clients/reach_client.rs +++ b/frontend/sdks/invoke/src/clients/reach_client.rs @@ -34,13 +34,7 @@ impl ReachClient { funs.web_client().put_obj_to_str(&format!("{reach_url}/ci/message/send"), &req, headers.clone()).await?; Ok(()) } - pub async fn general_send( - to: &str, - template_id: &str, - replacement: &HashMap, - funs: &TardisFunsInst, - ctx: &TardisContext - ) -> TardisResult<()> { + pub async fn general_send(to: &str, template_id: &str, replacement: &HashMap, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { let reach_url: String = BaseSpiClient::module_url(InvokeModuleKind::Reach, funs).await?; let headers = BaseSpiClient::headers(None, funs, ctx).await?; funs.web_client().put_obj_to_str(&format!("{reach_url}/cc/msg/general/{to}/template/{template_id}"), &replacement, headers.clone()).await?;