From db807ffc4fa4ee9794900bc138bc0ba836214421 Mon Sep 17 00:00:00 2001 From: ZzIsGod1019 <1498852723@qq.com> Date: Thu, 4 Jul 2024 18:11:06 +0800 Subject: [PATCH 1/2] flow: fix bug (#796) --- .../flow/src/api/ca/flow_ca_model_api.rs | 46 ++- .../flow/src/api/cc/flow_cc_model_api.rs | 82 +---- .../flow/src/api/ci/flow_ci_inst_api.rs | 19 + .../flow/src/api/ci/flow_ci_model_api.rs | 76 +++- .../flow/src/api/ci/flow_ci_state_api.rs | 25 +- .../flow/src/api/ct/flow_ct_model_api.rs | 73 ++-- .../middlewares/flow/src/domain/flow_inst.rs | 7 + .../flow/src/dto/flow_model_dto.rs | 22 +- .../flow/src/dto/flow_state_dto.rs | 2 +- .../flow/src/dto/flow_transition_dto.rs | 2 + .../middlewares/flow/src/dto/flow_var_dto.rs | 1 + .../middlewares/flow/src/flow_initializer.rs | 103 +----- backend/middlewares/flow/src/serv/clients.rs | 1 + .../flow/src/serv/clients/log_client.rs | 103 ++++++ .../flow/src/serv/clients/search_client.rs | 4 +- .../flow/src/serv/flow_inst_serv.rs | 199 ++++++++--- .../flow/src/serv/flow_model_serv.rs | 330 +++++++++++++----- .../flow/src/serv/flow_state_serv.rs | 164 ++++++++- .../flow/tests/test_flow_scenes_fsm.rs | 10 + .../src/serv/pg/search_pg_item_serv.rs | 12 +- .../spi/spi-stats/src/dto/stats_conf_dto.rs | 2 +- .../api/iam_ci_account_api.rs | 44 ++- 22 files changed, 943 insertions(+), 384 deletions(-) create mode 100644 backend/middlewares/flow/src/serv/clients/log_client.rs diff --git a/backend/middlewares/flow/src/api/ca/flow_ca_model_api.rs b/backend/middlewares/flow/src/api/ca/flow_ca_model_api.rs index c87287ad3..f4432e819 100644 --- a/backend/middlewares/flow/src/api/ca/flow_ca_model_api.rs +++ b/backend/middlewares/flow/src/api/ca/flow_ca_model_api.rs @@ -12,9 +12,9 @@ use tardis::{ }; use crate::{ - dto::flow_model_dto::{FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelCopyOrReferenceReq}, + dto::flow_model_dto::{FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelCopyOrReferenceReq, FlowModelSingleCopyOrReferenceReq}, flow_constants, - serv::flow_model_serv::FlowModelServ, + serv::{flow_inst_serv::FlowInstServ, flow_model_serv::FlowModelServ}, }; #[derive(Clone)] @@ -35,8 +35,8 @@ impl FlowCaModelApi { ) -> TardisApiResult> { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; + let _orginal_models = FlowModelServ::clean_rel_models(None, None, None, &funs, &ctx.0).await?; let mut result = HashMap::new(); - let orginal_models = FlowModelServ::find_rel_models(None, true, &funs, &ctx.0).await?; let mock_ctx = match req.0.op { FlowModelAssociativeOperationKind::Copy => ctx.0.clone(), FlowModelAssociativeOperationKind::Reference => TardisContext { @@ -44,15 +44,43 @@ impl FlowCaModelApi { ..ctx.0.clone() }, }; - for (tag, rel_model_id) in req.0.rel_model_ids { - let orginal_model_id = orginal_models.get(&tag).map(|orginal_model| orginal_model.id.clone()); - result.insert( - rel_model_id.clone(), - FlowModelServ::copy_or_reference_model(orginal_model_id, &rel_model_id, Some(ctx.0.own_paths.clone()), &req.0.op, Some(false), &funs, &mock_ctx).await?, - ); + for (_, rel_model_id) in req.0.rel_model_ids { + let new_model = FlowModelServ::copy_or_reference_model(&rel_model_id, Some(ctx.0.own_paths.clone()), &req.0.op, Some(false), &funs, &mock_ctx).await?; + FlowInstServ::batch_update_when_switch_model(None, &new_model.tag, &new_model.id, new_model.states.clone(), &new_model.init_state_id, &funs, &ctx.0).await?; + + result.insert(rel_model_id.clone(), new_model); } + funs.commit().await?; ctx.0.execute_task().await?; TardisResp::ok(result) } + + /// Creating or referencing single model + /// + /// 创建或引用单个模型 + #[oai(path = "/copy_or_reference_single_model", method = "post")] + async fn copy_or_reference_single_model( + &self, + req: Json, + ctx: TardisContextExtractor, + _request: &Request, + ) -> TardisApiResult { + let mut funs = flow_constants::get_tardis_inst(); + funs.begin().await?; + let _orginal_models = FlowModelServ::clean_rel_models(None, None, Some(vec![req.0.tag.clone()]), &funs, &ctx.0).await?; + let mock_ctx = match req.0.op { + FlowModelAssociativeOperationKind::Copy => ctx.0.clone(), + FlowModelAssociativeOperationKind::Reference => TardisContext { + own_paths: rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.0.own_paths).unwrap_or_default(), + ..ctx.0.clone() + }, + }; + let new_model = FlowModelServ::copy_or_reference_model(&req.0.rel_model_id, Some(ctx.0.own_paths.clone()), &req.0.op, Some(false), &funs, &mock_ctx).await?; + FlowInstServ::batch_update_when_switch_model(None, &new_model.tag, &new_model.id, new_model.states.clone(), &new_model.init_state_id, &funs, &ctx.0).await?; + + funs.commit().await?; + ctx.0.execute_task().await?; + TardisResp::ok(new_model) + } } diff --git a/backend/middlewares/flow/src/api/cc/flow_cc_model_api.rs b/backend/middlewares/flow/src/api/cc/flow_cc_model_api.rs index 479e3dadd..4fbf1e650 100644 --- a/backend/middlewares/flow/src/api/cc/flow_cc_model_api.rs +++ b/backend/middlewares/flow/src/api/cc/flow_cc_model_api.rs @@ -1,11 +1,8 @@ use std::collections::HashMap; -use bios_basic::rbum::dto::rbum_filer_dto::{RbumBasicFilterReq, RbumItemRelFilterReq}; -use bios_basic::rbum::rbum_enumeration::RbumRelFromKind; +use bios_basic::rbum::dto::rbum_filer_dto::RbumBasicFilterReq; use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation; use itertools::Itertools; -use tardis::basic::dto::TardisContext; -use tardis::futures::future::join_all; use tardis::web::context_extractor::TardisContextExtractor; use tardis::web::poem::Request; use tardis::web::poem_openapi; @@ -21,7 +18,6 @@ use crate::dto::flow_state_dto::FlowStateRelModelModifyReq; use crate::dto::flow_transition_dto::{FlowTransitionModifyReq, FlowTransitionSortStatesReq}; use crate::flow_constants; use crate::serv::flow_model_serv::FlowModelServ; -use crate::serv::flow_rel_serv::{FlowRelKind, FlowRelServ}; #[derive(Clone)] pub struct FlowCcModelApi; @@ -83,70 +79,7 @@ impl FlowCcModelApi { _request: &Request, ) -> TardisApiResult> { let funs = flow_constants::get_tardis_inst(); - let mut result = vec![]; - let mut not_bind_template_models = join_all( - FlowModelServ::find_items( - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, - with_sub_own_paths: false, - ..Default::default() - }, - tags: Some(vec![tag.0.clone()]), - template: template.0, - ..Default::default() - }, - Some(true), - None, - &funs, - &ctx.0, - ) - .await? - .into_iter() - .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() { - Some(model) - } else { - None - } - }), - ) - .await - .into_iter() - .flatten() - .collect_vec(); - result.append(&mut not_bind_template_models); - if let Some(rel_template_id) = rel_template_id.0 { - let mut rel_template_models = FlowModelServ::find_items( - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, - with_sub_own_paths: false, - ..Default::default() - }, - tags: Some(vec![tag.0.clone()]), - template: template.0, - rel: Some(RbumItemRelFilterReq { - optional: false, - rel_by_from: true, - tag: Some(FlowRelKind::FlowModelTemplate.to_string()), - from_rbum_kind: Some(RbumRelFromKind::Item), - rel_item_id: Some(rel_template_id), - ..Default::default() - }), - ..Default::default() - }, - Some(true), - None, - &funs, - &ctx.0, - ) - .await?; - result.append(&mut rel_template_models); - } - TardisResp::ok(result) + TardisResp::ok(FlowModelServ::find_models_by_rel_template_id(tag.0, template.0, rel_template_id.0, &funs, &ctx.0).await?) } /// Find Models @@ -414,7 +347,16 @@ impl FlowCcModelApi { async fn modify_rel_state(&self, flow_model_id: Path, req: Json, ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; - FlowModelServ::modify_rel_state_ext(&flow_model_id.0, &req.0, &funs, &ctx.0).await?; + FlowModelServ::modify_model( + &flow_model_id.0, + &mut FlowModelModifyReq { + modify_states: Some(vec![req.0]), + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?; funs.commit().await?; ctx.0.execute_task().await?; TardisResp::ok(Void {}) 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 6fd110c4c..e75d0e25c 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 @@ -249,4 +249,23 @@ impl FlowCiInstApi { }); TardisResp::ok(Void {}) } + + ///Script: update tag information for current instance + /// + /// 数据修复脚本:更新当前实例的tag信息 + #[oai(path = "/reflesh_inst_tag", method = "post")] + async fn reflesh_inst_tag(&self) -> TardisApiResult { + let funs = flow_constants::get_tardis_inst(); + tokio::spawn(async move { + match FlowInstServ::reflesh_inst_tag(&funs).await { + Ok(_) => { + log::trace!("[Flow.Inst] add log success") + } + Err(e) => { + log::warn!("[Flow.Inst] failed to add log:{e}") + } + } + }); + 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 39c1ecaab..9721ac2ce 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 @@ -5,6 +5,7 @@ use crate::dto::flow_model_dto::{ FlowModelFilterReq, FlowModelFindRelStateResp, }; use crate::flow_constants; +use crate::serv::flow_inst_serv::FlowInstServ; use crate::serv::flow_model_serv::FlowModelServ; use crate::serv::flow_rel_serv::{FlowRelKind, FlowRelServ}; use bios_basic::rbum::dto::rbum_filer_dto::RbumBasicFilterReq; @@ -14,6 +15,7 @@ use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation; use itertools::Itertools; use std::iter::Iterator; use tardis::basic::dto::TardisContext; +use tardis::log::warn; use tardis::web::context_extractor::TardisContextExtractor; use tardis::web::poem::Request; use tardis::web::poem_openapi; @@ -105,7 +107,7 @@ impl FlowCiModelApi { /// Creating or referencing models /// - /// 创建或引用模型(rel_model_id:关联模型ID, op:关联模型操作类型(复制或者引用),is_create_copy:是否创建副本(当op为复制时需指定,默认不需要)) + /// #[oai(path = "/copy_or_reference_model", method = "post")] async fn copy_or_reference_model( &self, @@ -116,6 +118,8 @@ impl FlowCiModelApi { let mut funs = flow_constants::get_tardis_inst(); check_without_owner_and_unsafe_fill_ctx(request, &funs, &mut ctx.0)?; funs.begin().await?; + warn!("ci copy_or_reference_model req: {:?}", req.0); + let orginal_models = FlowModelServ::clean_rel_models(None, None, None, &funs, &ctx.0).await?; // find rel models let rel_model_ids = FlowRelServ::find_to_simple_rels( &FlowRelKind::FlowModelTemplate, @@ -130,12 +134,8 @@ impl FlowCiModelApi { .map(|rel| rel.rel_id) .collect_vec(); let mut result = HashMap::new(); - let mut orginal_models = HashMap::new(); let mut mock_ctx = ctx.0.clone(); - if rbum_scope_helper::get_scope_level_by_context(&ctx.0)? == RbumScopeLevelKind::L1 { - orginal_models = FlowModelServ::find_rel_models(req.0.rel_template_id.clone(), true, &funs, &ctx.0).await?; - } else if rbum_scope_helper::get_scope_level_by_context(&ctx.0)? == RbumScopeLevelKind::L2 { - orginal_models = FlowModelServ::find_rel_models(None, true, &funs, &ctx.0).await?; + if rbum_scope_helper::get_scope_level_by_context(&ctx.0)? == RbumScopeLevelKind::L2 { mock_ctx = match req.0.op { FlowModelAssociativeOperationKind::Copy => ctx.0.clone(), FlowModelAssociativeOperationKind::Reference => TardisContext { @@ -144,14 +144,23 @@ impl FlowCiModelApi { }, }; } - for rel_model_id in rel_model_ids { - let tag = FlowModelServ::get_item_detail_aggs(&rel_model_id, false, &funs, &mock_ctx).await?.tag; - let orginal_model_id = orginal_models.get(&tag).map(|orginal_model| orginal_model.id.clone()); - result.insert( - rel_model_id.clone(), - FlowModelServ::copy_or_reference_model(orginal_model_id, &rel_model_id, Some(ctx.0.own_paths.clone()), &req.0.op, Some(false), &funs, &mock_ctx).await?.id, - ); + let new_model = FlowModelServ::copy_or_reference_model(&rel_model_id, Some(ctx.0.own_paths.clone()), &req.0.op, Some(false), &funs, &mock_ctx).await?; + FlowInstServ::batch_update_when_switch_model( + if rbum_scope_helper::get_scope_level_by_context(&ctx.0)? == RbumScopeLevelKind::L2 { + None + } else { + orginal_models.get(&new_model.tag).map(|model| model.id.clone()) + }, + &new_model.tag, + &new_model.id, + new_model.states.clone(), + &new_model.init_state_id, + &funs, + &ctx.0, + ) + .await?; + result.insert(rel_model_id.clone(), new_model.id.clone()); } funs.commit().await?; ctx.0.execute_task().await?; @@ -195,8 +204,7 @@ impl FlowCiModelApi { ) .await? { - let added_model = - FlowModelServ::copy_or_reference_model(None, &from_model.rel_model_id, None, &FlowModelAssociativeOperationKind::Copy, Some(true), &funs, &ctx.0).await?; + let added_model = FlowModelServ::copy_or_reference_model(&from_model.rel_model_id, None, &FlowModelAssociativeOperationKind::Copy, Some(true), &funs, &ctx.0).await?; FlowRelServ::add_simple_rel( &FlowRelKind::FlowModelTemplate, &added_model.id, @@ -240,11 +248,43 @@ impl FlowCiModelApi { async fn exist_rel_by_template_ids(&self, req: Json, mut ctx: TardisContextExtractor, request: &Request) -> TardisApiResult> { let funs = flow_constants::get_tardis_inst(); check_without_owner_and_unsafe_fill_ctx(request, &funs, &mut ctx.0)?; + warn!("ci exist_rel_by_template_ids req: {:?}", req.0); + let support_tags = req.0.support_tags; let mut result = vec![]; - for rel_template_id in req.0.rel_template_ids { - if !FlowRelServ::find_to_simple_rels(&FlowRelKind::FlowModelTemplate, &rel_template_id, None, None, &funs, &ctx.0).await?.is_empty() { - result.push(rel_template_id.clone()); + for (rel_template_id, current_tags) in req.0.rel_tag_by_template_ids { + // 当前模板tag和需要支持的tag取交集,得到当前模板tag中需要检查的tag列表 + let tags = current_tags.into_iter().filter(|current_tag| support_tags.contains(current_tag)).collect_vec(); + if !tags.is_empty() { + // 当前模板关联的模型所支持的tag + let rel_model_tags = FlowModelServ::find_items( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ids: Some( + FlowRelServ::find_to_simple_rels(&FlowRelKind::FlowModelTemplate, &rel_template_id, None, None, &funs, &ctx.0) + .await? + .into_iter() + .map(|rel| rel.rel_id) + .collect_vec(), + ), + ..Default::default() + }, + ..Default::default() + }, + None, + None, + &funs, + &ctx.0, + ) + .await? + .into_iter() + .map(|model| model.tag.clone()) + .collect_vec(); + // 如果出现了当前模板tag中需要检查的tag没有被当前模板关联,则说明当前关联模板不是可用状态 + if !tags.into_iter().filter(|tag| !rel_model_tags.contains(tag)).collect_vec().is_empty() { + continue; + } } + result.push(rel_template_id.clone()); } TardisResp::ok(result) diff --git a/backend/middlewares/flow/src/api/ci/flow_ci_state_api.rs b/backend/middlewares/flow/src/api/ci/flow_ci_state_api.rs index ecf430d3c..c8b1973c8 100644 --- a/backend/middlewares/flow/src/api/ci/flow_ci_state_api.rs +++ b/backend/middlewares/flow/src/api/ci/flow_ci_state_api.rs @@ -2,12 +2,15 @@ use bios_basic::rbum::dto::rbum_filer_dto::RbumBasicFilterReq; use bios_basic::rbum::helper::rbum_scope_helper::{self, check_without_owner_and_unsafe_fill_ctx}; use bios_basic::rbum::rbum_enumeration::RbumScopeLevelKind; use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation; +use tardis::basic::dto::TardisContext; +use tardis::log; +use tardis::tokio; use tardis::web::context_extractor::TardisContextExtractor; use tardis::web::poem::Request; use tardis::web::poem_openapi; use tardis::web::poem_openapi::param::Query; use tardis::web::poem_openapi::payload::Json; -use tardis::web::web_resp::{TardisApiResult, TardisPage, TardisResp}; +use tardis::web::web_resp::{TardisApiResult, TardisPage, TardisResp, Void}; use crate::dto::flow_state_dto::{FlowStateCountGroupByStateReq, FlowStateCountGroupByStateResp, FlowStateFilterReq, FlowStateKind, FlowStateSummaryResp, FlowSysStateKind}; use crate::flow_constants; @@ -103,4 +106,24 @@ impl FlowCiStateApi { ctx.0.execute_task().await?; TardisResp::ok(result) } + + ///Script: merge global states with the same name + /// + /// 脚本:合并相同名称的全局状态 + #[oai(path = "/merge_state_by_name", method = "post")] + async fn merge_state_by_name(&self) -> TardisApiResult { + let funs = flow_constants::get_tardis_inst(); + let global_ctx = TardisContext::default(); + tokio::spawn(async move { + match FlowStateServ::merge_state_by_name(&funs, &global_ctx).await { + Ok(_) => { + log::trace!("[Flow.Inst] add log success") + } + Err(e) => { + log::warn!("[Flow.Inst] failed to add log:{e}") + } + } + }); + TardisResp::ok(Void {}) + } } diff --git a/backend/middlewares/flow/src/api/ct/flow_ct_model_api.rs b/backend/middlewares/flow/src/api/ct/flow_ct_model_api.rs index 260714615..14aa2dc46 100644 --- a/backend/middlewares/flow/src/api/ct/flow_ct_model_api.rs +++ b/backend/middlewares/flow/src/api/ct/flow_ct_model_api.rs @@ -2,20 +2,21 @@ use std::collections::HashMap; use bios_basic::rbum::{dto::rbum_filer_dto::RbumBasicFilterReq, serv::rbum_item_serv::RbumItemCrudOperation}; use itertools::Itertools; -use tardis::web::{ - context_extractor::TardisContextExtractor, - poem::{web::Json, Request}, - poem_openapi::{self, param::Path}, - web_resp::{TardisApiResult, TardisResp, Void}, +use tardis::{ + basic::error::TardisError, + web::{ + context_extractor::TardisContextExtractor, + poem::{web::Json, Request}, + poem_openapi::{self, param::Path}, + web_resp::{TardisApiResult, TardisResp, Void}, + }, }; use crate::{ - dto::flow_model_dto::{ - FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelCopyOrReferenceReq, FlowModelExistRelByTemplateIdsReq, FlowModelFilterReq, - FlowModelFindRelNameByTemplateIdsReq, - }, + dto::flow_model_dto::{FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelCopyOrReferenceReq, FlowModelFilterReq, FlowModelFindRelNameByTemplateIdsReq}, flow_constants, serv::{ + flow_inst_serv::FlowInstServ, flow_model_serv::FlowModelServ, flow_rel_serv::{FlowRelKind, FlowRelServ}, }, @@ -38,17 +39,29 @@ impl FlowCtModelApi { _request: &Request, ) -> TardisApiResult> { let mut funs = flow_constants::get_tardis_inst(); + if req.0.rel_template_id.is_none() { + return TardisResp::err(TardisError::bad_request("rel_template_id can't be empty", "")); + } funs.begin().await?; + let orginal_models = FlowModelServ::clean_rel_models( + req.0.rel_template_id.clone(), + Some(req.0.rel_model_ids.clone().values().cloned().collect_vec()), + None, + &funs, + &ctx.0, + ) + .await?; let mut result = HashMap::new(); - let orginal_models = FlowModelServ::find_rel_models(req.0.rel_template_id.clone(), true, &funs, &ctx.0).await?; for (tag, rel_model_id) in req.0.rel_model_ids { let orginal_model_id = orginal_models.get(&tag).map(|orginal_model| orginal_model.id.clone()); - - let added_model = FlowModelServ::copy_or_reference_model(orginal_model_id, &rel_model_id, None, &req.0.op, Some(true), &funs, &ctx.0).await?; + if orginal_model_id.clone().unwrap_or_default() == rel_model_id { + continue; + } + let new_model = FlowModelServ::copy_or_reference_model(&rel_model_id, None, &req.0.op, Some(true), &funs, &ctx.0).await?; if let Some(rel_template_id) = &req.0.rel_template_id { FlowRelServ::add_simple_rel( &FlowRelKind::FlowModelTemplate, - &added_model.id, + &new_model.id, rel_template_id, None, None, @@ -60,7 +73,17 @@ impl FlowCtModelApi { ) .await?; } - result.insert(rel_model_id.clone(), added_model); + FlowInstServ::batch_update_when_switch_model( + orginal_model_id, + &new_model.tag, + &new_model.id, + new_model.states.clone(), + &new_model.init_state_id, + &funs, + &ctx.0, + ) + .await?; + result.insert(rel_model_id.clone(), new_model); } funs.commit().await?; ctx.0.execute_task().await?; @@ -80,6 +103,7 @@ impl FlowCtModelApi { ) -> TardisApiResult> { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; + let orginal_models = FlowModelServ::clean_rel_models(Some(to_template_id.0.clone()), None, None, &funs, &ctx.0).await?; let mut result = HashMap::new(); for from_model in FlowModelServ::find_detail_items( &FlowModelFilterReq { @@ -103,11 +127,10 @@ impl FlowCtModelApi { ) .await? { - let added_model = - FlowModelServ::copy_or_reference_model(None, &from_model.rel_model_id, None, &FlowModelAssociativeOperationKind::Copy, Some(true), &funs, &ctx.0).await?; + let new_model = FlowModelServ::copy_or_reference_model(&from_model.rel_model_id, None, &FlowModelAssociativeOperationKind::Copy, Some(true), &funs, &ctx.0).await?; FlowRelServ::add_simple_rel( &FlowRelKind::FlowModelTemplate, - &added_model.id, + &new_model.id, &to_template_id.0, None, None, @@ -118,7 +141,17 @@ impl FlowCtModelApi { &ctx.0, ) .await?; - result.insert(from_model.rel_model_id.clone(), added_model); + FlowInstServ::batch_update_when_switch_model( + orginal_models.get(&new_model.tag).map(|orginal_model| orginal_model.id.clone()), + &new_model.tag, + &new_model.id, + new_model.states.clone(), + &new_model.init_state_id, + &funs, + &ctx.0, + ) + .await?; + result.insert(from_model.rel_model_id.clone(), new_model); } funs.commit().await?; ctx.0.execute_task().await?; @@ -147,8 +180,8 @@ impl FlowCtModelApi { async fn find_rel_name_by_template_ids( &self, req: Json, - mut ctx: TardisContextExtractor, - request: &Request, + ctx: TardisContextExtractor, + _request: &Request, ) -> TardisApiResult>> { let funs = flow_constants::get_tardis_inst(); let mut result = HashMap::new(); diff --git a/backend/middlewares/flow/src/domain/flow_inst.rs b/backend/middlewares/flow/src/domain/flow_inst.rs index fde060526..900f54d91 100644 --- a/backend/middlewares/flow/src/domain/flow_inst.rs +++ b/backend/middlewares/flow/src/domain/flow_inst.rs @@ -18,6 +18,13 @@ pub struct Model { #[index(unique = true)] pub rel_business_obj_id: String, + /// Tags / 标签 + /// + /// Used for model classification + /// 用于模型分类 + #[index] + #[tardis_entity(custom_type = "String")] + pub tag: Option, /// Current state / 当前状态 /// /// This state needs to be updated after each transfer diff --git a/backend/middlewares/flow/src/dto/flow_model_dto.rs b/backend/middlewares/flow/src/dto/flow_model_dto.rs index 2f6c1a2d1..79d50e11a 100644 --- a/backend/middlewares/flow/src/dto/flow_model_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_model_dto.rs @@ -114,6 +114,7 @@ pub struct FlowModelSummaryResp { pub init_state_id: String, pub owner: String, + pub own_paths: String, pub create_time: DateTime, pub update_time: DateTime, /// 标签 @@ -335,7 +336,18 @@ pub struct FlowModelCopyOrReferenceReq { pub rel_model_ids: HashMap, /// 关联的模板ID pub rel_template_id: Option, - /// 修改的模板ID + /// 关联操作 + pub op: FlowModelAssociativeOperationKind, +} + +/// 创建或引用模型请求 +#[derive(Serialize, Deserialize, Debug, poem_openapi::Object)] +pub struct FlowModelSingleCopyOrReferenceReq { + /// 关联的模型ID列表 + pub tag: String, + /// 关联的模型ID + pub rel_model_id: String, + /// 关联操作 pub op: FlowModelAssociativeOperationKind, } @@ -344,15 +356,17 @@ pub struct FlowModelCopyOrReferenceReq { pub struct FlowModelCopyOrReferenceCiReq { /// 关联的模板ID pub rel_template_id: Option, - /// 修改的模板ID + /// 关联操作 pub op: FlowModelAssociativeOperationKind, } /// 检查关联模板请求 #[derive(Serialize, Deserialize, Debug, poem_openapi::Object)] pub struct FlowModelExistRelByTemplateIdsReq { - /// 关联的模板ID - pub rel_template_ids: Vec, + /// 关联的模板中的tag信息 + pub rel_tag_by_template_ids: HashMap>, + /// 需要支持关联的tag + pub support_tags: Vec, } /// 获取关联的模型名请求 diff --git a/backend/middlewares/flow/src/dto/flow_state_dto.rs b/backend/middlewares/flow/src/dto/flow_state_dto.rs index 674b0097d..3635ac842 100644 --- a/backend/middlewares/flow/src/dto/flow_state_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_state_dto.rs @@ -201,7 +201,7 @@ pub struct FlowStateRelModelModifyReq { } /// 工作流状态聚合信息 -#[derive(poem_openapi::Object, Serialize, Deserialize, Debug)] +#[derive(poem_openapi::Object, Serialize, Deserialize, Debug, Clone)] pub struct FlowStateAggResp { pub id: String, pub name: String, diff --git a/backend/middlewares/flow/src/dto/flow_transition_dto.rs b/backend/middlewares/flow/src/dto/flow_transition_dto.rs index 04ae0490d..86eb4136c 100644 --- a/backend/middlewares/flow/src/dto/flow_transition_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_transition_dto.rs @@ -113,6 +113,8 @@ pub struct FlowTransitionModifyReq { pub action_by_post_callback: Option, /// 后置动作的配置信息 pub action_by_post_changes: Option>, + pub action_by_post_var_changes: Option>, + pub action_by_post_state_changes: Option>, /// 前置动作的配置信息 pub action_by_front_changes: Option>, /// 排序 diff --git a/backend/middlewares/flow/src/dto/flow_var_dto.rs b/backend/middlewares/flow/src/dto/flow_var_dto.rs index 7d4f5cd33..601f4580d 100644 --- a/backend/middlewares/flow/src/dto/flow_var_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_var_dto.rs @@ -49,6 +49,7 @@ pub struct DefaultValue { pub value_type: DefaultValueType, pub value: Value, pub ext: Value, + pub value_name: Option, } #[derive(Display, Clone, Debug, PartialEq, Eq, Deserialize, Serialize, poem_openapi::Enum, strum::EnumString)] diff --git a/backend/middlewares/flow/src/flow_initializer.rs b/backend/middlewares/flow/src/flow_initializer.rs index c67354c82..a06c7aed0 100644 --- a/backend/middlewares/flow/src/flow_initializer.rs +++ b/backend/middlewares/flow/src/flow_initializer.rs @@ -2,7 +2,7 @@ use bios_basic::rbum::{ dto::{rbum_domain_dto::RbumDomainAddReq, rbum_filer_dto::RbumBasicFilterReq, rbum_kind_dto::RbumKindAddReq}, rbum_enumeration::RbumScopeLevelKind, rbum_initializer, - serv::{rbum_crud_serv::RbumCrudOperation, rbum_domain_serv::RbumDomainServ, rbum_item_serv::RbumItemCrudOperation, rbum_kind_serv::RbumKindServ, rbum_rel_serv::RbumRelServ}, + serv::{rbum_crud_serv::RbumCrudOperation, rbum_domain_serv::RbumDomainServ, rbum_item_serv::RbumItemCrudOperation, rbum_kind_serv::RbumKindServ}, }; use bios_sdk_invoke::invoke_initializer; @@ -15,7 +15,6 @@ use tardis::{ sea_orm::{ self, sea_query::{Expr, Query, Table}, - ColumnTrait, EntityTrait, QueryFilter, }, }, futures::future::join_all, @@ -36,7 +35,7 @@ use crate::{ domain::{flow_inst, flow_model, flow_state, flow_transition}, dto::{ flow_model_dto::FlowModelFilterReq, - flow_state_dto::{FlowStateFilterReq, FlowStateModifyReq, FlowStateSummaryResp, FlowSysStateKind}, + flow_state_dto::FlowSysStateKind, flow_transition_dto::{FlowTransitionDoubleCheckInfo, FlowTransitionInitInfo}, }, flow_config::{BasicInfo, FlowBasicInfoManager, FlowConfig}, @@ -89,7 +88,6 @@ pub async fn init_db(mut funs: TardisFunsInst) -> TardisResult<()> { funs.begin().await?; if check_initialized(&funs, &ctx).await? { init_basic_info(&funs).await?; - merge_state_by_name(&funs, &ctx).await?; rebind_model_with_template(&funs, &ctx).await?; } else { let db_kind = TardisFuns::reldb().backend(); @@ -104,101 +102,6 @@ pub async fn init_db(mut funs: TardisFunsInst) -> TardisResult<()> { Ok(()) } -pub async fn merge_state_by_name(funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let kind_state_id = RbumKindServ::get_rbum_kind_id_by_code(flow_constants::RBUM_KIND_STATE_CODE, funs) - .await? - .ok_or_else(|| funs.err().not_found("flow", "merge_state_by_name", "not found state kind", ""))?; - let states = FlowStateServ::find_items( - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, - own_paths: Some("".to_string()), - rel_ctx_owner: true, - rbum_kind_id: Some(kind_state_id), - ..Default::default() - }, - ..Default::default() - }, - None, - None, - funs, - ctx, - ) - .await?; - let mut exists_states: HashMap = HashMap::new(); - for state in states { - if let Some(exists_state) = exists_states.get(&state.name) { - // flow inst - flow_inst::Entity::update_many() - .col_expr(flow_inst::Column::CurrentStateId, Expr::value(exists_state.id.as_str())) - .filter(flow_inst::Column::CurrentStateId.eq(&state.id)) - .exec(funs.db().raw_conn()) - .await?; - // flow model - flow_model::Entity::update_many() - .col_expr(flow_model::Column::InitStateId, Expr::value(exists_state.id.as_str())) - .filter(flow_model::Column::InitStateId.eq(&state.id)) - .exec(funs.db().raw_conn()) - .await?; - // flow transition - flow_transition::Entity::update_many() - .col_expr(flow_transition::Column::FromFlowStateId, Expr::value(exists_state.id.as_str())) - .filter(flow_transition::Column::FromFlowStateId.eq(&state.id)) - .exec(funs.db().raw_conn()) - .await?; - flow_transition::Entity::update_many() - .col_expr(flow_transition::Column::ToFlowStateId, Expr::value(exists_state.id.as_str())) - .filter(flow_transition::Column::ToFlowStateId.eq(&state.id)) - .exec(funs.db().raw_conn()) - .await?; - // rbum rel - join_all( - RbumRelServ::find_to_rels("FlowModelState", &state.id, None, None, funs, ctx) - .await? - .into_iter() - .map(|rel| async move { - let mock_ctx = TardisContext { - own_paths: rel.rel.own_paths, - ..Default::default() - }; - FlowRelServ::add_simple_rel( - &FlowRelKind::FlowModelState, - &rel.rel.from_rbum_id, - &exists_state.id, - None, - None, - false, - true, - Some(rel.rel.ext), - funs, - &mock_ctx, - ) - .await - .unwrap(); - FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelState, &rel.rel.from_rbum_id, &rel.rel.to_rbum_item_id, funs, &mock_ctx).await.unwrap(); - }) - .collect::>(), - ) - .await; - // flow state - FlowStateServ::modify_item( - &exists_state.id, - &mut FlowStateModifyReq { - tags: Some([exists_state.tags.clone().split(',').map(|s| s.to_string()).collect_vec(), vec![state.tags]].concat()), - ..Default::default() - }, - funs, - ctx, - ) - .await?; - FlowStateServ::delete_item(&state.id, funs, ctx).await?; - } else { - exists_states.insert(state.name.clone(), state); - } - } - Ok(()) -} - async fn check_initialized(funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { RbumDomainServ::exist_rbum( &RbumBasicFilterReq { @@ -1119,7 +1022,7 @@ async fn init_ws_search_client() -> Option { } } -use std::{collections::HashMap, sync::OnceLock}; +use std::sync::OnceLock; tardis::tardis_static! { pub(crate) async ws_flow_client: Option = init_ws_flow_client(); pub(crate) async ws_search_client: Option = init_ws_search_client(); diff --git a/backend/middlewares/flow/src/serv/clients.rs b/backend/middlewares/flow/src/serv/clients.rs index 03913fc58..c9a08e6f8 100644 --- a/backend/middlewares/flow/src/serv/clients.rs +++ b/backend/middlewares/flow/src/serv/clients.rs @@ -1,2 +1,3 @@ pub mod event_client; +pub mod log_client; pub mod search_client; diff --git a/backend/middlewares/flow/src/serv/clients/log_client.rs b/backend/middlewares/flow/src/serv/clients/log_client.rs new file mode 100644 index 000000000..7865617c5 --- /dev/null +++ b/backend/middlewares/flow/src/serv/clients/log_client.rs @@ -0,0 +1,103 @@ +use bios_sdk_invoke::clients::spi_log_client::SpiLogClient; +use serde::Serialize; + +use serde_json::Value; +use tardis::{ + basic::{dto::TardisContext, result::TardisResult}, + tokio, TardisFuns, TardisFunsInst, +}; + +use crate::flow_constants; +pub struct FlowLogClient; + +#[derive(Serialize, Default, Debug, Clone)] +pub struct LogParamContent { + pub subject: String, + pub name: String, + pub sub_kind: String, +} + +pub enum LogParamTag { + DynamicLog, +} + +impl From for String { + fn from(val: LogParamTag) -> Self { + match val { + LogParamTag::DynamicLog => "dynamic_log".to_string(), + } + } +} + +impl FlowLogClient { + pub async fn add_ctx_task( + tag: LogParamTag, + key: Option, + content: LogParamContent, + ext: Option, + kind: Option, + op_kind: Option, + rel_key: Option, + ctx: &TardisContext, + ) -> TardisResult<()> { + let ctx_clone = ctx.clone(); + ctx.add_async_task(Box::new(|| { + Box::pin(async move { + let task_handle = tokio::spawn(async move { + let funs = flow_constants::get_tardis_inst(); + Self::add_item( + tag, + content, + ext, + kind, + key.clone(), + op_kind, + rel_key, + Some(tardis::chrono::Utc::now().to_rfc3339()), + &funs, + &ctx_clone, + ) + .await + .unwrap(); + }); + task_handle.await.unwrap(); + Ok(()) + }) + })) + .await + } + + pub async fn add_item( + tag: LogParamTag, + content: LogParamContent, + ext: Option, + kind: Option, + key: Option, + op: Option, + rel_key: Option, + ts: Option, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult<()> { + // generate log item + let tag: String = tag.into(); + let own_paths = if ctx.own_paths.len() < 2 { None } else { Some(ctx.own_paths.clone()) }; + let owner = if ctx.owner.len() < 2 { None } else { Some(ctx.owner.clone()) }; + SpiLogClient::add( + &tag, + &TardisFuns::json.obj_to_string(&content).expect("req_msg not a valid json value"), + ext, + kind, + key, + op, + rel_key, + ts, + owner, + own_paths, + funs, + ctx, + ) + .await?; + Ok(()) + } +} diff --git a/backend/middlewares/flow/src/serv/clients/search_client.rs b/backend/middlewares/flow/src/serv/clients/search_client.rs index 9a0b36a0f..e087ffb73 100644 --- a/backend/middlewares/flow/src/serv/clients/search_client.rs +++ b/backend/middlewares/flow/src/serv/clients/search_client.rs @@ -21,9 +21,9 @@ use crate::{ const SEARCH_TAG: &str = "flow_model"; -pub struct IamSearchClient; +pub struct FlowSearchClient; -impl IamSearchClient { +impl FlowSearchClient { pub async fn async_add_or_modify_model_search(model_id: &str, is_modify: Box, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { let ctx_clone = ctx.clone(); let mock_ctx = TardisContext { diff --git a/backend/middlewares/flow/src/serv/flow_inst_serv.rs b/backend/middlewares/flow/src/serv/flow_inst_serv.rs index 324769c37..e6843be0a 100644 --- a/backend/middlewares/flow/src/serv/flow_inst_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_inst_serv.rs @@ -40,7 +40,7 @@ use crate::{ FlowInstTransferResp, FlowInstTransitionInfo, FlowOperationContext, }, flow_model_dto::{FlowModelDetailResp, FlowModelFilterReq}, - flow_state_dto::{FlowStateFilterReq, FlowStateRelModelExt, FlowSysStateKind}, + flow_state_dto::{FlowStateAggResp, FlowStateFilterReq, FlowStateRelModelExt, FlowSysStateKind}, flow_transition_dto::{FlowTransitionDetailResp, FlowTransitionFrontActionInfo}, flow_var_dto::FillType, }, @@ -89,6 +89,7 @@ impl FlowInstServ { }; let flow_inst: flow_inst::ActiveModel = flow_inst::ActiveModel { id: Set(inst_id.clone()), + tag: Set(Some(flow_model.tag.clone())), rel_flow_model_id: Set(flow_model_id.to_string()), rel_business_obj_id: Set(start_req.rel_business_obj_id.to_string()), @@ -199,7 +200,7 @@ impl FlowInstServ { query.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::RelFlowModelId)).eq(flow_model_id)); } if let Some(tag) = &filter.tag { - query.and_where(Expr::col((flow_model::Entity, flow_model::Column::Tag)).eq(tag)); + query.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::Tag)).eq(tag)); } if let Some(finish) = filter.finish { if finish { @@ -1188,70 +1189,158 @@ impl FlowInstServ { Ok(current_vars.unwrap_or_default().get(key).cloned()) } - pub async fn unsafe_update_state_by_inst_id(inst_id: String, modify_model_id: String, state_id: String, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let global_ctx = TardisContext { - own_paths: "".to_string(), - ..ctx.clone() - }; - let flow_inst_detail = Self::find_detail(vec![inst_id.clone()], funs, ctx).await?.pop().ok_or_else(|| { - funs.err().not_found( - "flow_inst", - "unsafe_update_state_by_inst_id", - &format!("flow instance {} not found", inst_id.clone()), - "404-flow-inst-not-found", - ) - })?; + pub async fn batch_update_when_switch_model( + original_model_id: Option, + tag: &str, + modify_model_id: &str, + modify_model_states: Vec, + state_id: &str, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult<()> { + let mut update_statement = Query::update(); + update_statement.table(flow_inst::Entity); + update_statement.value(flow_inst::Column::RelFlowModelId, modify_model_id); + update_statement.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::Tag)).eq(tag)); + if let Some(original_model_id) = &original_model_id { + update_statement.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::RelFlowModelId)).eq(original_model_id)); + } else { + update_statement.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::OwnPaths)).eq(ctx.own_paths.as_str())); + } + funs.db().execute(&update_statement).await?; - let flow_inst = flow_inst::ActiveModel { - id: Set(inst_id.clone()), - current_state_id: Set(state_id.clone()), - transitions: Set(Some(vec![])), - ..Default::default() - }; - funs.db().update_one(flow_inst, ctx).await?; - let modify_model_detail = FlowModelServ::get_item(&modify_model_id, &FlowModelFilterReq::default(), funs, ctx).await?; - let prev_flow_state = FlowStateServ::get_item( - &flow_inst_detail.current_state_id, - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - ..Default::default() - }, + FlowInstServ::unsafe_update_state_by_tag(original_model_id, tag, modify_model_id, modify_model_states, state_id, funs, ctx).await?; + Ok(()) + } + + async fn unsafe_update_state_by_tag( + original_model_id: Option, + tag: &str, + modify_model_id: &str, + modify_model_states: Vec, + state_id: &str, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult<()> { + let insts = Self::find_details( + &FlowInstFilterReq { + flow_model_id: original_model_id, + tag: Some(tag.to_string()), ..Default::default() }, funs, - &global_ctx, + ctx, ) - .await?; - let next_flow_state = FlowStateServ::get_item( - &modify_model_detail.init_state_id, - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - ..Default::default() - }, + .await? + .into_iter() + .filter(|inst| !modify_model_states.iter().any(|state| state.id == inst.current_state_id)) + .collect_vec(); + join_all( + insts + .iter() + .map(|inst| async { + let global_ctx = TardisContext::default(); + + let flow_inst = flow_inst::ActiveModel { + id: Set(inst.id.clone()), + current_state_id: Set(state_id.to_string()), + transitions: Set(Some(vec![])), + ..Default::default() + }; + funs.db().update_one(flow_inst, ctx).await.unwrap(); + let modify_model_detail = FlowModelServ::get_item(modify_model_id, &FlowModelFilterReq::default(), funs, 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( + &modify_model_detail.tag, + &inst.id, + &inst.rel_business_obj_id, + "".to_string(), + FlowSysStateKind::default(), + next_flow_state.name.clone(), + next_flow_state.sys_state, + "".to_string(), + false, + Some(FlowExternalCallbackOp::Default), + ctx, + funs, + ) + .await + }) + .collect_vec(), + ) + .await + .into_iter() + .collect::>>()?; + Ok(()) + } + + pub async fn reflesh_inst_tag(funs: &TardisFunsInst) -> TardisResult<()> { + let global_ctx = TardisContext::default(); + let mut query = Query::select(); + Self::package_ext_query( + &mut query, + &FlowInstFilterReq { + with_sub: Some(true), ..Default::default() }, funs, &global_ctx, ) .await?; - - FlowExternalServ::do_notify_changes( - &modify_model_detail.tag, - &flow_inst_detail.id, - &flow_inst_detail.rel_business_obj_id, - prev_flow_state.name.clone(), - prev_flow_state.sys_state, - next_flow_state.name.clone(), - next_flow_state.sys_state, - "".to_string(), - false, - None, - ctx, - funs, - ) - .await?; + query.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::Tag)).is_null()); + loop { + let (flow_insts, _) = funs.db().paginate_dtos::(&query, 1, 2000).await?; + if flow_insts.is_empty() { + break; + } + join_all( + flow_insts + .iter() + .map(|inst| async { + let model = FlowModelServ::get_item( + &inst.rel_flow_model_id, + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + ..Default::default() + }, + ..Default::default() + }, + funs, + &global_ctx, + ) + .await; + if let Ok(model) = model { + let flow_inst = flow_inst::ActiveModel { + id: Set(inst.id.clone()), + tag: Set(Some(model.tag.clone())), + ..Default::default() + }; + funs.db().update_one(flow_inst, &global_ctx).await + } else { + Ok(()) + } + }) + .collect_vec(), + ) + .await + .into_iter() + .collect::>>()?; + } Ok(()) } } diff --git a/backend/middlewares/flow/src/serv/flow_model_serv.rs b/backend/middlewares/flow/src/serv/flow_model_serv.rs index 6965856ec..6dcb62552 100644 --- a/backend/middlewares/flow/src/serv/flow_model_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_model_serv.rs @@ -3,12 +3,12 @@ use std::{collections::HashMap, vec}; use async_recursion::async_recursion; use bios_basic::rbum::{ dto::{ - rbum_filer_dto::RbumBasicFilterReq, + rbum_filer_dto::{RbumBasicFilterReq, RbumItemRelFilterReq}, rbum_item_dto::{RbumItemKernelAddReq, RbumItemKernelModifyReq}, rbum_rel_dto::RbumRelModifyReq, }, helper::rbum_scope_helper, - rbum_enumeration::RbumScopeLevelKind, + rbum_enumeration::{RbumRelFromKind, RbumScopeLevelKind}, serv::{ rbum_crud_serv::{ID_FIELD, NAME_FIELD, REL_DOMAIN_ID_FIELD, REL_KIND_ID_FIELD}, rbum_item_serv::{RbumItemCrudOperation, RBUM_ITEM_TABLE}, @@ -20,7 +20,7 @@ use tardis::{ chrono::Utc, db::sea_orm::{ sea_query::{Alias, Cond, Expr, Query, SelectStatement}, - EntityName, EntityTrait, JoinType, Order, QueryFilter, Set, Value, + EntityName, EntityTrait, JoinType, Order, QueryFilter, Set, }, futures::future::join_all, serde_json::json, @@ -30,9 +30,8 @@ use tardis::{ }; use crate::{ - domain::{flow_inst, flow_model, flow_state, flow_transition}, + domain::{flow_model, flow_state, flow_transition}, dto::{ - flow_inst_dto::FlowInstFilterReq, flow_model_dto::{ FlowModelAddReq, FlowModelAggResp, FlowModelAssociativeOperationKind, FlowModelBindStateReq, FlowModelDetailResp, FlowModelFilterReq, FlowModelFindRelStateResp, FlowModelModifyReq, FlowModelSummaryResp, @@ -49,7 +48,10 @@ use crate::{ use async_trait::async_trait; use super::{ - clients::search_client::IamSearchClient, + clients::{ + log_client::{FlowLogClient, LogParamContent, LogParamTag}, + search_client::FlowSearchClient, + }, flow_inst_serv::FlowInstServ, flow_rel_serv::{FlowRelKind, FlowRelServ}, }; @@ -131,7 +133,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() { - IamSearchClient::async_delete_model_search(flow_model_id.to_string(), funs, ctx).await?; + 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: "工作流模板".to_string(), + name: detail.as_ref().unwrap().name.clone(), + sub_kind: "flow_template".to_string(), + }, + 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), + ctx, + ) + .await?; } Ok(()) } @@ -571,7 +642,13 @@ impl FlowModelServ { funs.db().insert_many(flow_transitions, ctx).await } - pub async fn modify_transitions(flow_model_id: &str, modify_req: &[FlowTransitionModifyReq], funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + pub async fn modify_transitions( + flow_model_id: &str, + modify_req: &[FlowTransitionModifyReq], + model_detail: &FlowModelDetailResp, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult<()> { let flow_state_ids = modify_req .iter() .filter(|req| req.from_flow_state_id.is_some()) @@ -621,8 +698,13 @@ impl FlowModelServ { "404-flow-transition-rel-model-not-legal", )); } - + let model_transitions = model_detail.transitions(); 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() @@ -682,6 +764,19 @@ impl FlowModelServ { 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()); } @@ -979,7 +1074,6 @@ impl FlowModelServ { /// rel_own_paths: 绑定实例ID(仅在引用且不创建模型时生效) /// (rel_model_id:关联模型ID, rel_template_id: 绑定模板ID,可选参数(仅在创建模型,即创建副本或op为复制时生效), op:关联模型操作类型(复制或者引用),is_create_copy:是否创建副本(当op为复制时需指定,默认不需要)) pub async fn copy_or_reference_model( - orginal_model_id: Option, rel_model_id: &str, rel_own_paths: Option, op: &FlowModelAssociativeOperationKind, @@ -1053,69 +1147,6 @@ impl FlowModelServ { }; let new_model = Self::get_item_detail_aggs(&result, true, funs, ctx).await?; - if let Some(orginal_model_id) = orginal_model_id { - let global_ctx = TardisContext { - own_paths: "".to_string(), - ..ctx.clone() - }; - let orginal_model_detail = Self::get_item( - &orginal_model_id, - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - ids: Some(vec![orginal_model_id.to_string()]), - ignore_scope: true, - with_sub_own_paths: true, - ..Default::default() - }, - ..Default::default() - }, - funs, - &global_ctx, - ) - .await?; - - // modify instance rel_model_id and state_id - let mut update_statement = Query::update(); - update_statement.table(flow_inst::Entity); - update_statement.value(flow_inst::Column::RelFlowModelId, Value::from(new_model.id.clone())); - update_statement.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::RelFlowModelId)).eq(orginal_model_detail.id.as_str())); - update_statement.and_where(Expr::col((flow_inst::Entity, flow_inst::Column::OwnPaths)).eq(mock_ctx.own_paths.as_str())); - funs.db().execute(&update_statement).await?; - for modify_state in orginal_model_detail.states().into_iter().filter(|state| !new_model.states.iter().any(|new_state| new_state.id == state.id)).collect_vec() { - join_all( - FlowInstServ::find_details( - &FlowInstFilterReq { - flow_model_id: Some(orginal_model_detail.id.clone()), - current_state_id: Some(modify_state.id.clone()), - ..Default::default() - }, - funs, - &mock_ctx, - ) - .await? - .iter() - .map(|inst| async { - FlowInstServ::unsafe_update_state_by_inst_id(inst.id.clone(), new_model.id.clone(), new_model.init_state_id.clone(), funs, &mock_ctx).await - }) - .collect_vec(), - ) - .await - .into_iter() - .collect::>>()?; - } - - // delete model - for rel in FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelPath, &orginal_model_id, None, None, funs, &global_ctx).await? { - FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelPath, &orginal_model_id, &rel.rel_id, funs, &global_ctx).await?; - } - if orginal_model_detail.own_paths == mock_ctx.own_paths { - for rel in FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTemplate, &orginal_model_id, None, None, funs, &global_ctx).await? { - FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelTemplate, &orginal_model_id, &rel.rel_id, funs, &global_ctx).await?; - } - Self::delete_item(&orginal_model_id, funs, &mock_ctx).await?; - } - } - Ok(new_model) } @@ -1501,10 +1532,27 @@ impl FlowModelServ { let mut result = None; // Prioritize confirming the existence of mods related to own_paths - if let Some(rel_model_id) = - FlowRelServ::find_to_simple_rels(&FlowRelKind::FlowModelPath, &ctx.own_paths, None, None, funs, ctx).await?.into_iter().map(|rel| rel.rel_id).collect_vec().pop() + if let Some(rel_model) = Self::find_items( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ids: Some( + FlowRelServ::find_to_simple_rels(&FlowRelKind::FlowModelPath, &ctx.own_paths, None, None, funs, ctx).await?.into_iter().map(|rel| rel.rel_id).collect_vec(), + ), + ignore_scope: true, + ..Default::default() + }, + ..Default::default() + }, + None, + None, + funs, + ctx, + ) + .await? + .into_iter() + .find(|rel_model| rel_model.tag.as_str() == tag) { - return Ok(rel_model_id); + return Ok(rel_model.id); } // try get model in tenant path or app path while !own_paths.is_empty() { @@ -1553,4 +1601,128 @@ impl FlowModelServ { None => Err(funs.err().not_found("flow_inst_serv", "get_model_id_by_own_paths", "model not found", "404-flow-model-not-found")), } } + + pub async fn find_models_by_rel_template_id( + tag: String, + template: Option, + rel_template_id: Option, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult> { + let mut result = vec![]; + let mut not_bind_template_models = join_all( + FlowModelServ::find_items( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ignore_scope: true, + with_sub_own_paths: false, + ..Default::default() + }, + tags: Some(vec![tag.clone()]), + template, + rel_model_ids: Some(vec!["".to_string()]), // rel_model_id is empty and template is true, which means it is a workflow template. + ..Default::default() + }, + Some(true), + None, + funs, + ctx, + ) + .await? + .into_iter() + .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() { + Some(model) + } else { + None + } + }), + ) + .await + .into_iter() + .flatten() + .collect_vec(); + result.append(&mut not_bind_template_models); + if let Some(rel_template_id) = rel_template_id { + let mut rel_template_models = FlowModelServ::find_items( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ignore_scope: true, + with_sub_own_paths: false, + ..Default::default() + }, + tags: Some(vec![tag.clone()]), + template, + rel_model_ids: Some(vec!["".to_string()]), // rel_model_id is empty and template is true, which means it is a workflow template. + rel: Some(RbumItemRelFilterReq { + optional: false, + rel_by_from: true, + tag: Some(FlowRelKind::FlowModelTemplate.to_string()), + from_rbum_kind: Some(RbumRelFromKind::Item), + rel_item_id: Some(rel_template_id), + ..Default::default() + }), + ..Default::default() + }, + Some(true), + None, + funs, + ctx, + ) + .await?; + result.append(&mut rel_template_models); + } + + Ok(result.into_iter().filter(|model| !model.init_state_id.is_empty()).collect_vec()) + } + + // 清除当前关联的模型数据(用于更新配置) + /** + * 当rel_template_id为空时: + * 1、去除ModelPath引用关系 + * 2、删除当前own_path下的model + * 当rel_template_id不为空时: + * 1、去除ModelTemplate引用关系 + * 2、去除ModelPath引用关系 + * 3、删除当前rel_template_id下的model + */ + pub async fn clean_rel_models( + rel_template_id: Option, + orginal_model_ids: Option>, + spec_tags: Option>, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult> { + let global_ctx = TardisContext { + own_paths: "".to_string(), + ..ctx.clone() + }; + let models = Self::find_rel_models(rel_template_id.clone(), false, funs, ctx).await?; + for (tag, model) in models.iter() { + if let Some(spec_tags) = spec_tags.clone() { + if !spec_tags.contains(tag) { + continue; + } + } + if let Some(orginal_model_ids) = orginal_model_ids.clone() { + if orginal_model_ids.contains(&model.id) { + continue; + } + } + for rel in FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelPath, &model.id, None, None, funs, &global_ctx).await? { + FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelPath, &model.id, &rel.rel_id, funs, &global_ctx).await?; + } + if rel_template_id.clone().is_some() { + for rel in FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelTemplate, &model.id, None, None, funs, &global_ctx).await? { + FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelTemplate, &model.id, &rel.rel_id, funs, &global_ctx).await?; + } + } + if ctx.own_paths == model.own_paths { + Self::delete_item(&model.id, funs, ctx).await?; + } + } + Ok(models) + } } diff --git a/backend/middlewares/flow/src/serv/flow_state_serv.rs b/backend/middlewares/flow/src/serv/flow_state_serv.rs index 43219740c..a4e8ac936 100644 --- a/backend/middlewares/flow/src/serv/flow_state_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_state_serv.rs @@ -7,21 +7,22 @@ use bios_basic::rbum::{ }, helper::rbum_scope_helper, rbum_enumeration::RbumScopeLevelKind, - serv::rbum_item_serv::RbumItemCrudOperation, + serv::{rbum_item_serv::RbumItemCrudOperation, rbum_kind_serv::RbumKindServ, rbum_rel_serv::RbumRelServ}, }; use itertools::Itertools; use tardis::{ basic::{dto::TardisContext, field::TrimString, result::TardisResult}, db::sea_orm::{ sea_query::{Cond, Expr, SelectStatement}, - EntityName, Set, + ColumnTrait, EntityName, EntityTrait, QueryFilter, Set, }, + futures::future::join_all, serde_json::json, TardisFuns, TardisFunsInst, }; use crate::{ - domain::flow_state, + domain::{flow_inst, flow_model, flow_state, flow_transition}, dto::{ flow_model_dto::FlowModelFilterReq, flow_state_dto::{ @@ -30,10 +31,12 @@ use crate::{ }, }, flow_config::FlowBasicInfoManager, + flow_constants, }; use async_trait::async_trait; use super::{ + clients::log_client::{FlowLogClient, LogParamContent, LogParamTag}, flow_inst_serv::FlowInstServ, flow_model_serv::FlowModelServ, flow_rel_serv::{FlowRelKind, FlowRelServ}, @@ -86,6 +89,25 @@ impl RbumItemCrudOperation TardisResult<()> { + FlowLogClient::add_ctx_task( + LogParamTag::DynamicLog, + Some(id.to_string()), + LogParamContent { + subject: "工作流状态".to_string(), + name: add_req.name.clone().unwrap_or_default().to_string(), + sub_kind: "flow_state".to_string(), + }, + None, + Some("dynamic_log_tenant_config".to_string()), + Some("新建".to_string()), + rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.own_paths), + ctx, + ) + .await?; + Ok(()) + } + async fn before_modify_item(_id: &str, _modify_req: &mut FlowStateModifyReq, _funs: &TardisFunsInst, _ctx: &TardisContext) -> TardisResult<()> { // Modifications are allowed only where non-key fields are modified or not used // if (modify_req.scope_level.is_some() @@ -100,6 +122,24 @@ impl RbumItemCrudOperation TardisResult<()> { + FlowLogClient::add_ctx_task( + LogParamTag::DynamicLog, + Some(id.to_string()), + LogParamContent { + subject: "工作流状态".to_string(), + name: Self::get_item(id, &FlowStateFilterReq::default(), funs, ctx).await?.name, + sub_kind: "flow_state".to_string(), + }, + None, + Some("dynamic_log_tenant_config".to_string()), + Some("编辑".to_string()), + rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.own_paths), + ctx, + ) + .await?; + Ok(()) + } async fn package_item_modify(_: &str, modify_req: &FlowStateModifyReq, _: &TardisFunsInst, _: &TardisContext) -> TardisResult> { if modify_req.name.is_none() && modify_req.scope_level.is_none() && modify_req.disabled.is_none() { return Ok(None); @@ -164,7 +204,28 @@ impl RbumItemCrudOperation, _funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + if let Some(detail) = detail { + FlowLogClient::add_ctx_task( + LogParamTag::DynamicLog, + Some(id.to_string()), + LogParamContent { + subject: "工作流状态".to_string(), + name: detail.name.clone(), + sub_kind: "flow_state".to_string(), + }, + None, + Some("dynamic_log_tenant_config".to_string()), + Some("删除".to_string()), + rbum_scope_helper::get_path_item(RbumScopeLevelKind::L1.to_int(), &ctx.own_paths), + ctx, + ) + .await?; + } + Ok(()) } async fn package_ext_query(query: &mut SelectStatement, _: bool, filter: &FlowStateFilterReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { @@ -348,4 +409,99 @@ impl FlowStateServ { } Ok(result.into_values().collect_vec()) } + + pub async fn merge_state_by_name(funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let kind_state_id = RbumKindServ::get_rbum_kind_id_by_code(flow_constants::RBUM_KIND_STATE_CODE, funs) + .await? + .ok_or_else(|| funs.err().not_found("flow", "merge_state_by_name", "not found state kind", ""))?; + let states = Self::find_items( + &FlowStateFilterReq { + basic: RbumBasicFilterReq { + ignore_scope: true, + own_paths: Some("".to_string()), + rel_ctx_owner: true, + rbum_kind_id: Some(kind_state_id), + ..Default::default() + }, + ..Default::default() + }, + None, + None, + funs, + ctx, + ) + .await?; + let mut exists_states: HashMap = HashMap::new(); + for state in states { + if let Some(exists_state) = exists_states.get(&state.name) { + // flow inst + flow_inst::Entity::update_many() + .col_expr(flow_inst::Column::CurrentStateId, Expr::value(exists_state.id.as_str())) + .filter(flow_inst::Column::CurrentStateId.eq(&state.id)) + .exec(funs.db().raw_conn()) + .await?; + // flow model + flow_model::Entity::update_many() + .col_expr(flow_model::Column::InitStateId, Expr::value(exists_state.id.as_str())) + .filter(flow_model::Column::InitStateId.eq(&state.id)) + .exec(funs.db().raw_conn()) + .await?; + // flow transition + flow_transition::Entity::update_many() + .col_expr(flow_transition::Column::FromFlowStateId, Expr::value(exists_state.id.as_str())) + .filter(flow_transition::Column::FromFlowStateId.eq(&state.id)) + .exec(funs.db().raw_conn()) + .await?; + flow_transition::Entity::update_many() + .col_expr(flow_transition::Column::ToFlowStateId, Expr::value(exists_state.id.as_str())) + .filter(flow_transition::Column::ToFlowStateId.eq(&state.id)) + .exec(funs.db().raw_conn()) + .await?; + // rbum rel + join_all( + RbumRelServ::find_to_rels("FlowModelState", &state.id, None, None, funs, ctx) + .await? + .into_iter() + .map(|rel| async move { + let mock_ctx = TardisContext { + own_paths: rel.rel.own_paths, + ..Default::default() + }; + FlowRelServ::add_simple_rel( + &FlowRelKind::FlowModelState, + &rel.rel.from_rbum_id, + &exists_state.id, + None, + None, + false, + true, + Some(rel.rel.ext), + funs, + &mock_ctx, + ) + .await + .unwrap(); + FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelState, &rel.rel.from_rbum_id, &rel.rel.to_rbum_item_id, funs, &mock_ctx).await.unwrap(); + }) + .collect::>(), + ) + .await; + // flow state + Self::modify_item( + &exists_state.id, + &mut FlowStateModifyReq { + tags: Some(vec![]), + ..Default::default() + }, + funs, + ctx, + ) + .await?; + Self::delete_item(&state.id, funs, ctx).await?; + } else { + exists_states.insert(state.name.clone(), state); + } + } + Ok(()) + } } diff --git a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs index 69b6b10d0..4a380da3e 100644 --- a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs +++ b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs @@ -246,6 +246,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { changed_val: None, changed_kind: None, }]), + action_by_post_var_changes: None, + action_by_post_state_changes: None, double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, content: Some("再次确认该操作生效".to_string()), @@ -300,6 +302,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { changed_kind: Some(FlowTransitionActionByVarChangeInfoChangedKind::SelectField), }, ]), + action_by_post_var_changes: None, + action_by_post_state_changes: None, double_check: None, is_notify: None, sort: None, @@ -322,6 +326,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { action_by_pre_callback: None, action_by_post_callback: None, action_by_post_changes: None, + action_by_post_var_changes: None, + action_by_post_state_changes: None, action_by_front_changes: None, double_check: None, is_notify: None, @@ -386,6 +392,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { changed_val: None, changed_kind: None, }]), + action_by_post_var_changes: None, + action_by_post_state_changes: None, double_check: None, is_notify: None, sort: None, @@ -431,6 +439,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { changed_val: None, changed_kind: None, }]), + action_by_post_var_changes: None, + action_by_post_state_changes: None, double_check: None, is_notify: None, sort: None, diff --git a/backend/spi/spi-search/src/serv/pg/search_pg_item_serv.rs b/backend/spi/spi-search/src/serv/pg/search_pg_item_serv.rs index 9851ad906..5a528f063 100644 --- a/backend/spi/spi-search/src/serv/pg/search_pg_item_serv.rs +++ b/backend/spi/spi-search/src/serv/pg/search_pg_item_serv.rs @@ -218,8 +218,16 @@ fn generate_word_combinations_with_length(original_str: &str, split_len: usize) fn generate_word_combinations_with_symbol(original_str: &str, symbols: Vec<&str>) -> Vec { let mut combinations = Vec::new(); for symbol in symbols { - let mut splited_words = original_str.split(symbol).collect_vec(); - combinations.append(&mut splited_words); + let splited_words = original_str.split(symbol).collect_vec(); + if splited_words.len() == 1 { + continue; + } + for i in 0..splited_words.len() { + for j in i..splited_words.len() { + let word = splited_words[i..=j].join(symbol); + combinations.push(word); + } + } } combinations.into_iter().map(|word| word.to_string()).collect_vec() } diff --git a/backend/spi/spi-stats/src/dto/stats_conf_dto.rs b/backend/spi/spi-stats/src/dto/stats_conf_dto.rs index 5f5f3e91b..1d2cc7f6f 100644 --- a/backend/spi/spi-stats/src/dto/stats_conf_dto.rs +++ b/backend/spi/spi-stats/src/dto/stats_conf_dto.rs @@ -443,7 +443,7 @@ pub struct StatsConfFactColInfoResp { /// 当kind = 度量时有效,用于指定度量激活(仅在所有指定维度都存在时激活) pub mes_act_by_dim_conf_keys: Option>, /// Associated fact key - /// + /// /// 关联的事实key pub rel_conf_fact_key: Option, /// Associated fact and fact column configuration. diff --git a/backend/supports/iam/src/console_interface/api/iam_ci_account_api.rs b/backend/supports/iam/src/console_interface/api/iam_ci_account_api.rs index d66169497..182056e3a 100644 --- a/backend/supports/iam/src/console_interface/api/iam_ci_account_api.rs +++ b/backend/supports/iam/src/console_interface/api/iam_ci_account_api.rs @@ -260,26 +260,34 @@ impl IamCiAccountApi { /// 通过三方凭证ak批量查找帐户 /// #[oai(path = "/batch-third-party", method = "get")] - async fn batch_by_third_party(&self, supplier: Query, aks: Query, mut ctx: TardisContextExtractor, request: &Request) -> TardisApiResult> { + async fn batch_by_third_party( + &self, + supplier: Query, + aks: Query, + mut ctx: TardisContextExtractor, + request: &Request, + ) -> TardisApiResult> { let funs = iam_constants::get_tardis_inst(); check_without_owner_and_unsafe_fill_ctx(request, &funs, &mut ctx.0)?; - let mut result=vec![]; - for ak in aks.0.split(','){ - let cert = IamCertServ::get_3th_kind_cert_by_ak(&supplier.0, &ak, true, &funs, &ctx.0).await?; - result.push(IamAccountServ::get_item( - &cert.rel_rbum_id, - &IamAccountFilterReq { - basic: RbumBasicFilterReq { - own_paths: Some("".to_string()), - with_sub_own_paths: true, - ..Default::default() - }, - ..Default::default() - }, - &funs, - &ctx.0, - ) - .await?); + let mut result = vec![]; + for ak in aks.0.split(',') { + let cert = IamCertServ::get_3th_kind_cert_by_ak(&supplier.0, &ak, true, &funs, &ctx.0).await?; + result.push( + IamAccountServ::get_item( + &cert.rel_rbum_id, + &IamAccountFilterReq { + basic: RbumBasicFilterReq { + own_paths: Some("".to_string()), + with_sub_own_paths: true, + ..Default::default() + }, + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?, + ); } TardisResp::ok(result) From c6b7f9c0bfb2c9e62c30b7ee805b09adad276a0e Mon Sep 17 00:00:00 2001 From: ZzIsGod1019 <1498852723@qq.com> Date: Fri, 5 Jul 2024 18:19:04 +0800 Subject: [PATCH 2/2] flow: fix bug (state filter by rel_model_ids) (#797) --- backend/middlewares/flow/src/serv/flow_event_serv.rs | 11 ++++++++++- backend/middlewares/flow/src/serv/flow_model_serv.rs | 9 ++------- backend/middlewares/flow/src/serv/flow_state_serv.rs | 6 ++---- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/backend/middlewares/flow/src/serv/flow_event_serv.rs b/backend/middlewares/flow/src/serv/flow_event_serv.rs index d3f291dba..44de3472b 100644 --- a/backend/middlewares/flow/src/serv/flow_event_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_event_serv.rs @@ -104,7 +104,16 @@ impl FlowEventServ { fn do_check_front_condition(current_vars: &HashMap, condition: &FlowTransitionFrontActionInfo) -> TardisResult { match condition.right_value { FlowTransitionFrontActionRightValue::ChangeContent => { - if let Some(left_value) = current_vars.get(&condition.left_value) { + let left_value = if let Some(custom_value) = + current_vars.get(&format!("custom_{}", condition.left_value)) + { + Some(custom_value) + } else if let Some(original_value) = current_vars.get(&condition.left_value) { + Some(original_value) + } else { + None + }; + if let Some(left_value) = left_value { Ok(condition.relevance_relation.check_conform( left_value.as_str().unwrap_or(left_value.to_string().as_str()).to_string(), condition diff --git a/backend/middlewares/flow/src/serv/flow_model_serv.rs b/backend/middlewares/flow/src/serv/flow_model_serv.rs index 6dcb62552..175fda088 100644 --- a/backend/middlewares/flow/src/serv/flow_model_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_model_serv.rs @@ -141,12 +141,6 @@ impl RbumItemCrudOperation