diff --git a/backend/middlewares/event/src/api/event_listener_api.rs b/backend/middlewares/event/src/api/event_listener_api.rs index 0035906bd..2b595e9c0 100644 --- a/backend/middlewares/event/src/api/event_listener_api.rs +++ b/backend/middlewares/event/src/api/event_listener_api.rs @@ -14,7 +14,6 @@ pub struct EventListenerApi; /// 事件监听器API #[poem_openapi::OpenApi(prefix_path = "/listener")] impl EventListenerApi { - /// Register event listener /// /// 注册事件监听器 diff --git a/backend/middlewares/event/src/api/event_proc_api.rs b/backend/middlewares/event/src/api/event_proc_api.rs index 32a8ea0e9..4f3f825e6 100644 --- a/backend/middlewares/event/src/api/event_proc_api.rs +++ b/backend/middlewares/event/src/api/event_proc_api.rs @@ -12,7 +12,6 @@ pub struct EventProcApi; /// 事件处理API #[poem_openapi::OpenApi(prefix_path = "/proc")] impl EventProcApi { - /// Process event /// /// 处理事件 diff --git a/backend/middlewares/flow/src/api/cc/flow_cc_inst_api.rs b/backend/middlewares/flow/src/api/cc/flow_cc_inst_api.rs index 51cd54ca9..c9820304a 100644 --- a/backend/middlewares/flow/src/api/cc/flow_cc_inst_api.rs +++ b/backend/middlewares/flow/src/api/cc/flow_cc_inst_api.rs @@ -147,8 +147,8 @@ impl FlowCcInstApi { TardisResp::ok(result) } - /// Modify Assigned[Deprecated] - /// 同步执行人信息[已废弃] + /// Modify Assigned [Deprecated] + /// 同步执行人信息 [已废弃] #[oai(path = "/:flow_inst_id/transition/modify_assigned", method = "post")] async fn modify_assigned( &self, 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 4231cbae4..ce4677cce 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 @@ -2,6 +2,7 @@ use std::collections::HashMap; use bios_basic::rbum::dto::rbum_filer_dto::RbumBasicFilterReq; use bios_basic::rbum::serv::rbum_item_serv::RbumItemCrudOperation; +use itertools::Itertools; use tardis::web::context_extractor::TardisContextExtractor; use tardis::web::poem::Request; use tardis::web::poem_openapi; @@ -13,18 +14,19 @@ use crate::dto::flow_model_dto::{ FlowModelAddCustomModelReq, FlowModelAddCustomModelResp, FlowModelAddReq, FlowModelAggResp, FlowModelBindStateReq, FlowModelFilterReq, FlowModelFindRelStateResp, FlowModelModifyReq, FlowModelSortStatesReq, FlowModelSummaryResp, FlowModelUnbindStateReq, FlowTemplateModelResp, }; -use crate::dto::flow_state_dto::FlowStateRelModelExt; -use crate::dto::flow_transition_dto::FlowTransitionSortStatesReq; +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; #[derive(Clone)] pub struct FlowCcModelApi; /// Flow model process API #[poem_openapi::OpenApi(prefix_path = "/cc/model")] impl FlowCcModelApi { - /// Add Model / 添加模型 + /// Add Model + /// + /// 添加模型 #[oai(path = "/", method = "post")] async fn add(&self, mut add_req: Json, ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult { let mut funs = flow_constants::get_tardis_inst(); @@ -34,7 +36,9 @@ impl FlowCcModelApi { TardisResp::ok(result) } - /// Modify Model By Model Id / 修改模型 + /// Modify Model By Model Id + /// + /// 修改模型 #[oai(path = "/:flow_model_id", method = "patch")] async fn modify(&self, flow_model_id: Path, mut modify_req: Json, ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult { let mut funs = flow_constants::get_tardis_inst(); @@ -44,7 +48,9 @@ impl FlowCcModelApi { TardisResp::ok(Void {}) } - /// Get Model By Model Id / 获取模型 + /// Get Model By Model Id + /// + /// 获取模型 #[oai(path = "/:flow_model_id", method = "get")] async fn get(&self, flow_model_id: Path, ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult { let funs = flow_constants::get_tardis_inst(); @@ -52,7 +58,9 @@ impl FlowCcModelApi { TardisResp::ok(result) } - /// Find Models / 获取模型列表 + /// Find Models + /// + /// 获取模型列表 #[oai(path = "/", method = "get")] #[allow(clippy::too_many_arguments)] async fn paginate( @@ -93,24 +101,34 @@ impl FlowCcModelApi { TardisResp::ok(result) } - /// Get Models By Tag And Template Id / 通过Tag和模板Id获取模型 - #[oai(path = "/get_models", method = "get")] - async fn get_models( + /// Find the specified models, or add it if it doesn't exist. + /// + /// 查找指定model,如果不存在则新增 + /// + /// # Parameters + /// - `tag_ids` - list of tag_id + /// - `temp_id` - associated template_id + /// - `is_shared` - whether the associated template is shared + #[oai(path = "/find_or_add_models", method = "put")] + async fn find_or_add_models( &self, tag_ids: Query, temp_id: Query>, + is_shared: Query>, ctx: TardisContextExtractor, _request: &Request, ) -> TardisApiResult> { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; let tag_ids: Vec<_> = tag_ids.split(',').collect(); - let result = FlowModelServ::get_models(tag_ids, temp_id.0, &funs, &ctx.0).await?; + let result = FlowModelServ::find_or_add_models(tag_ids, temp_id.0, is_shared.unwrap_or(false), &funs, &ctx.0).await?; funs.commit().await?; TardisResp::ok(result) } - /// Delete Model By Model Id / 删除模型 + /// Delete Model By Model Id + /// + /// 删除模型 /// /// Valid only when model is not used /// @@ -124,37 +142,82 @@ impl FlowCcModelApi { TardisResp::ok(Void {}) } - /// Bind State By Model Id / 绑定状态 + /// Bind State By Model Id [Deprecated] + /// + /// 绑定状态 [已废弃] #[oai(path = "/:flow_model_id/bind_state", method = "post")] async fn bind_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::bind_state(&FlowRelKind::FlowModelState, &flow_model_id.0, &req.0, &funs, &ctx.0).await?; + FlowModelServ::modify_model( + &flow_model_id.0, + &mut FlowModelModifyReq { + bind_states: Some(vec![req.0]), + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?; funs.commit().await?; TardisResp::ok(Void {}) } - /// Unbind State By Model Id / 解绑状态 + /// Unbind State By Model Id [Deprecated] + /// + /// 解绑状态 [已废弃] #[oai(path = "/:flow_model_id/unbind_state", method = "post")] async fn unbind_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::unbind_state(&FlowRelKind::FlowModelState, &flow_model_id.0, &req, &funs, &ctx.0).await?; + FlowModelServ::modify_model( + &flow_model_id.0, + &mut FlowModelModifyReq { + unbind_states: Some(vec![req.state_id.clone()]), + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?; funs.commit().await?; TardisResp::ok(Void {}) } - /// Resort states / 状态重新排序 + /// Resort states [Deprecated] + /// + /// 状态重新排序 [已废弃] #[oai(path = "/:flow_model_id/resort_state", method = "post")] async fn resort_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::resort_state(&FlowRelKind::FlowModelState, &flow_model_id.0, &req.0, &funs, &ctx.0).await?; + FlowModelServ::modify_model( + &flow_model_id.0, + &mut FlowModelModifyReq { + modify_states: Some( + req.0 + .sort_states + .into_iter() + .map(|state| FlowStateRelModelModifyReq { + id: state.state_id, + sort: Some(state.sort), + show_btns: None, + }) + .collect_vec(), + ), + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?; funs.commit().await?; TardisResp::ok(Void {}) } - /// Resort transitions / 动作重新排序 + /// Resort transitions [Deprecated] + /// + /// 动作重新排序 [已废弃] #[oai(path = "/:flow_model_id/resort_transition", method = "post")] async fn resort_transition( &self, @@ -165,27 +228,49 @@ impl FlowCcModelApi { ) -> TardisApiResult { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; - FlowModelServ::resort_transition(&flow_model_id.0, &req.0, &funs, &ctx.0).await?; + let modify_trans = req + .0 + .sort_states + .into_iter() + .map(|sort_req| FlowTransitionModifyReq { + id: sort_req.id.clone().into(), + sort: Some(sort_req.sort), + ..Default::default() + }) + .collect_vec(); + FlowModelServ::modify_model( + &flow_model_id.0, + &mut FlowModelModifyReq { + modify_transitions: Some(modify_trans), + ..Default::default() + }, + &funs, + &ctx.0, + ) + .await?; funs.commit().await?; TardisResp::ok(Void {}) } - /// add custom model by template_id / 添加自定义模型 + /// copy parent model to current own_paths + /// + /// 复制父级模型到当前 own_paths #[oai(path = "/add_custom_model", method = "post")] async fn add_custom_model(&self, req: Json, ctx: TardisContextExtractor, _request: &Request) -> TardisApiResult> { let mut funs = flow_constants::get_tardis_inst(); funs.begin().await?; - let proj_template_id = req.0.proj_template_id.unwrap_or_default(); let mut result = vec![]; - for item in req.0.bind_model_objs { - let model_id = FlowModelServ::add_custom_model(&item.tag, &proj_template_id, None, &funs, &ctx.0).await.ok(); - result.push(FlowModelAddCustomModelResp { tag: item.tag, model_id }); + for item in &req.0.bind_model_objs { + let model_id = FlowModelServ::add_custom_model(&item.tag, req.0.proj_template_id.clone(), None, &funs, &ctx.0).await.ok(); + result.push(FlowModelAddCustomModelResp { tag: item.tag.clone(), model_id }); } funs.commit().await?; TardisResp::ok(result) } - /// find rel states by model_id / 获取关联状态 + /// find rel states by model_id + /// + /// 获取关联状态 #[oai(path = "/find_rel_status", method = "get")] async fn find_rel_states( &self, @@ -200,19 +285,14 @@ impl FlowCcModelApi { TardisResp::ok(result) } - /// modify related state / 编辑关联的状态 - #[oai(path = "/:flow_model_id/modify_rel_state/:state_id", method = "patch")] - async fn modify_rel_state( - &self, - flow_model_id: Path, - state_id: Path, - req: Json, - ctx: TardisContextExtractor, - _request: &Request, - ) -> TardisApiResult { + /// modify related state [Deprecated] + /// + /// 编辑关联的状态 [已废弃] + #[oai(path = "/:flow_model_id/modify_rel_state", method = "patch")] + 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(&flow_model_id.0, &state_id.0, &req.0, &funs, &ctx.0).await?; + FlowModelServ::modify_rel_state_ext(&flow_model_id.0, &req.0, &funs, &ctx.0).await?; funs.commit().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 a81738619..ba924f393 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 @@ -17,7 +17,9 @@ pub struct FlowCiModelApi; /// Flow Config process API #[poem_openapi::OpenApi(prefix_path = "/ci/model")] impl FlowCiModelApi { - /// Get model detail / 获取模型详情 + /// Get model detail + /// + /// 获取模型详情 #[oai(path = "/detail", method = "get")] async fn get_detail( &self, @@ -50,7 +52,9 @@ impl FlowCiModelApi { TardisResp::ok(result) } - /// find rel states by model_id / 获取关联状态 + /// find rel states by model_id + /// + /// 获取关联状态 #[oai(path = "/find_rel_status", method = "get")] async fn find_rel_states( &self, @@ -66,7 +70,9 @@ impl FlowCiModelApi { TardisResp::ok(result) } - /// add custom model by template_id / 添加自定义模型 + /// add custom model by template_id + /// + /// 添加自定义模型 #[oai(path = "/add_custom_model", method = "post")] async fn add_custom_model( &self, @@ -77,10 +83,10 @@ 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?; - let proj_template_id = req.0.proj_template_id.unwrap_or_default(); + let proj_template_id = req.0.proj_template_id; let mut result = vec![]; for item in req.0.bind_model_objs { - let model_id = FlowModelServ::add_custom_model(&item.tag, &proj_template_id, None, &funs, &ctx.0).await.ok(); + let model_id = FlowModelServ::add_custom_model(&item.tag, proj_template_id.clone(), None, &funs, &ctx.0).await.ok(); result.push(FlowModelAddCustomModelResp { tag: item.tag, model_id }); } funs.commit().await?; diff --git a/backend/middlewares/flow/src/dto/flow_external_dto.rs b/backend/middlewares/flow/src/dto/flow_external_dto.rs index 7df5553ab..8f66fa97d 100644 --- a/backend/middlewares/flow/src/dto/flow_external_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_external_dto.rs @@ -9,19 +9,58 @@ use super::{flow_state_dto::FlowSysStateKind, flow_transition_dto::FlowTransitio #[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object)] pub struct FlowExternalReq { + /// Type of request initiated, ex: query field, modification field, status change notification... + /// + /// 发起请求的类型,例:查询字段,修改字段,状态变更通知.. pub kind: FlowExternalKind, + /// When kind is ModifyField, the field is modified in a specific way, for example: validate the content, post action, precondition trigger ... + /// + /// 当 kind 为 ModifyField 时,字段被修改的具体操作方式,例:验证内容,后置动作,前置条件触发.. pub callback_op: Option, + /// The tag corresponding to the current business + /// + /// 当前业务对应的 tag pub curr_tag: String, + /// Current Business ID + /// + /// 当前业务ID pub curr_bus_obj_id: String, + /// Workflow Instance ID + /// + /// 工作流实例ID pub inst_id: String, + /// Modified State ID + /// + /// 修改后的状态ID pub target_state: Option, + /// Modified state type + /// + /// 修改后的状态类型 pub target_sys_state: Option, + /// Status ID before modification + /// + /// 修改前的状态ID pub original_state: Option, + /// Type of state before modification + /// + /// 修改前的状态类型 pub original_sys_state: Option, + /// Name of the action actually triggered (business side logging operation) + /// + /// 实际触发的动作名称(业务方记录操作日志) pub transition_name: Option, pub owner_paths: String, + /// When kind is QueryField, batch pass business IDs + /// + /// 当 kind 为 QueryField 时,批量传入业务ID pub obj_ids: Vec, + /// Whether the request triggers a notification + /// + /// 请求是否触发通知 pub notify: Option, + /// 扩展字段 + /// + /// Extended params pub params: Vec, } diff --git a/backend/middlewares/flow/src/dto/flow_model_dto.rs b/backend/middlewares/flow/src/dto/flow_model_dto.rs index e86610241..438e2b8cb 100644 --- a/backend/middlewares/flow/src/dto/flow_model_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_model_dto.rs @@ -13,7 +13,7 @@ use tardis::{ }; use super::{ - flow_state_dto::FlowStateRelModelExt, + flow_state_dto::{FlowStateRelModelExt, FlowStateRelModelModifyReq}, flow_transition_dto::{FlowTransitionAddReq, FlowTransitionDetailResp, FlowTransitionModifyReq}, }; @@ -32,6 +32,8 @@ pub struct FlowModelAddReq { pub transitions: Option>, + pub states: Option>, + pub template: bool, pub rel_model_id: Option, @@ -58,6 +60,10 @@ pub struct FlowModelModifyReq { pub modify_transitions: Option>, pub delete_transitions: Option>, + pub bind_states: Option>, + pub unbind_states: Option>, + pub modify_states: Option>, + pub tag: Option, pub scope_level: Option, @@ -180,7 +186,7 @@ pub struct FlowTemplateModelResp { #[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object)] pub struct FlowModelBindStateReq { pub state_id: String, - pub sort: i64, + pub ext: FlowStateRelModelExt, } #[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object)] @@ -188,12 +194,12 @@ pub struct FlowModelUnbindStateReq { pub state_id: String, } -#[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object)] +#[derive(Serialize, Deserialize, Clone, Debug, Default, poem_openapi::Object)] pub struct FlowModelSortStatesReq { pub sort_states: Vec, } -#[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object)] +#[derive(Serialize, Deserialize, Debug, Default, Clone, poem_openapi::Object)] pub struct FlowModelSortStateInfoReq { pub state_id: String, pub sort: i64, diff --git a/backend/middlewares/flow/src/dto/flow_state_dto.rs b/backend/middlewares/flow/src/dto/flow_state_dto.rs index dfaeb25f3..f05ff3e1a 100644 --- a/backend/middlewares/flow/src/dto/flow_state_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_state_dto.rs @@ -187,3 +187,10 @@ pub struct FlowStateRelModelExt { pub sort: i64, pub show_btns: Option>, } + +#[derive(Serialize, Deserialize, Debug, Default, poem_openapi::Object, sea_orm::FromQueryResult)] +pub struct FlowStateRelModelModifyReq { + pub id: String, + pub sort: Option, + pub show_btns: Option>, +} diff --git a/backend/middlewares/flow/src/dto/flow_transition_dto.rs b/backend/middlewares/flow/src/dto/flow_transition_dto.rs index 13ac0c6a2..1d67ff514 100644 --- a/backend/middlewares/flow/src/dto/flow_transition_dto.rs +++ b/backend/middlewares/flow/src/dto/flow_transition_dto.rs @@ -3,7 +3,7 @@ use itertools::Itertools; use serde::{Deserialize, Serialize}; use strum::Display; use tardis::{ - basic::field::TrimString, + basic::{error::TardisError, field::TrimString}, db::sea_orm::{self, EnumIter}, serde_json::Value, web::poem_openapi, @@ -45,7 +45,7 @@ pub struct FlowTransitionAddReq { pub sort: Option, } -#[derive(Serialize, Deserialize, Debug, poem_openapi::Object)] +#[derive(Serialize, Deserialize, Debug, poem_openapi::Object, Default)] pub struct FlowTransitionModifyReq { #[oai(validator(min_length = "2", max_length = "255"))] pub id: TrimString, @@ -345,8 +345,8 @@ impl From for String { #[derive(Default)] pub struct FlowTransitionInitInfo { - pub from_flow_state_name: String, - pub to_flow_state_name: String, + pub from_flow_state_id: String, + pub to_flow_state_id: String, pub name: String, pub transfer_by_auto: Option, pub transfer_by_timer: Option, @@ -371,6 +371,36 @@ pub struct FlowTransitionInitInfo { pub sort: Option, } +impl TryFrom for FlowTransitionAddReq { + type Error = TardisError; + + fn try_from(value: FlowTransitionInitInfo) -> Result { + Ok(FlowTransitionAddReq { + from_flow_state_id: value.from_flow_state_id, + to_flow_state_id: value.to_flow_state_id, + name: Some(value.name.into()), + is_notify: Some(true), + transfer_by_auto: value.transfer_by_auto, + transfer_by_timer: value.transfer_by_timer, + guard_by_creator: value.guard_by_creator, + guard_by_his_operators: value.guard_by_his_operators, + guard_by_assigned: value.guard_by_assigned, + guard_by_spec_account_ids: value.guard_by_spec_account_ids, + guard_by_spec_role_ids: value.guard_by_spec_role_ids, + guard_by_spec_org_ids: value.guard_by_spec_org_ids, + guard_by_other_conds: value.guard_by_other_conds, + vars_collect: value.vars_collect, + action_by_pre_callback: value.action_by_pre_callback, + action_by_post_callback: value.action_by_post_callback, + action_by_post_changes: Some(value.action_by_post_changes), + action_by_front_changes: Some(value.action_by_front_changes), + double_check: value.double_check, + + sort: value.sort, + }) + } +} + #[derive(Serialize, Deserialize, Clone, PartialEq, Debug, poem_openapi::Object, sea_orm::FromJsonQueryResult)] pub struct FlowTransitionFrontActionInfo { pub relevance_relation: FlowTransitionFrontActionInfoRelevanceRelation, diff --git a/backend/middlewares/flow/src/flow_initializer.rs b/backend/middlewares/flow/src/flow_initializer.rs index 3a6c3b8d9..2a46e1683 100644 --- a/backend/middlewares/flow/src/flow_initializer.rs +++ b/backend/middlewares/flow/src/flow_initializer.rs @@ -29,7 +29,7 @@ use crate::{ }, flow_config::{BasicInfo, FlowBasicInfoManager, FlowConfig}, flow_constants, - serv::flow_model_serv::FlowModelServ, + serv::{flow_model_serv::FlowModelServ, flow_state_serv::FlowStateServ}, }; pub async fn init(web_server: &TardisWebServer) -> TardisResult<()> { @@ -196,20 +196,21 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard .pop(); if ticket_init_model.is_none() { // 工单模板初始化 + let mut bind_states = vec![]; + bind_states.push(FlowStateServ::init_state("TICKET", "待处理", FlowSysStateKind::Start, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TICKET", "处理中", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TICKET", "待确认", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TICKET", "已关闭", FlowSysStateKind::Finish, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TICKET", "已撤销", FlowSysStateKind::Finish, "", funs, ctx).await?); FlowModelServ::init_model( "TICKET", - vec![ - ("待处理", FlowSysStateKind::Start, ""), - ("处理中", FlowSysStateKind::Progress, ""), - ("待确认", FlowSysStateKind::Progress, ""), - ("已关闭", FlowSysStateKind::Finish, ""), - ("已撤销", FlowSysStateKind::Finish, ""), - ], + bind_states[0].clone(), + bind_states.clone(), "待处理-处理中-待确认-已关闭-已撤销", vec![ FlowTransitionInitInfo { - from_flow_state_name: "待处理".to_string(), - to_flow_state_name: "处理中".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[1].clone(), name: "立即处理".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -218,8 +219,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待处理".to_string(), - to_flow_state_name: "已撤销".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[4].clone(), name: "撤销".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -228,8 +229,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待处理".to_string(), - to_flow_state_name: "待确认".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[2].clone(), name: "处理完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -239,8 +240,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待处理".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[3].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -249,8 +250,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待确认".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[3].clone(), name: "确认解决".into(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -259,8 +260,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待确认".to_string(), - to_flow_state_name: "处理中".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[1].clone(), name: "未解决".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -291,20 +292,21 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard .records .pop(); if req_init_model.is_none() { + let mut bind_states = vec![]; + bind_states.push(FlowStateServ::init_state("REQ", "待开始", FlowSysStateKind::Start, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("REQ", "进行中", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("REQ", "已完成", FlowSysStateKind::Finish, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("REQ", "已关闭", FlowSysStateKind::Finish, "", funs, ctx).await?); // 需求模板初始化 FlowModelServ::init_model( "REQ", - vec![ - ("待开始", FlowSysStateKind::Start, ""), - ("进行中", FlowSysStateKind::Progress, ""), - ("已完成", FlowSysStateKind::Finish, ""), - ("已关闭", FlowSysStateKind::Finish, ""), - ], + bind_states[0].clone(), + bind_states.clone(), "待开始-进行中-已完成-已关闭", vec![ FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[1].clone(), name: "开始".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -313,8 +315,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[3].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -323,8 +325,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[2].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -333,8 +335,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[3].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -343,8 +345,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[1].clone(), name: "重新处理".into(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -353,8 +355,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[3].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -363,8 +365,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已关闭".to_string(), - to_flow_state_name: "待开始".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[0].clone(), name: "激活".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -395,21 +397,22 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard .records .pop(); if product_init_model.is_none() { + let mut bind_states = vec![]; + bind_states.push(FlowStateServ::init_state("PROJ", "待开始", FlowSysStateKind::Start, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("PROJ", "进行中", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("PROJ", "存在风险", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("PROJ", "已完成", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("PROJ", "已关闭", FlowSysStateKind::Finish, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("PROJ", "已归档", FlowSysStateKind::Finish, "", funs, ctx).await?); FlowModelServ::init_model( "PROJ", - vec![ - ("待开始", FlowSysStateKind::Start, ""), - ("进行中", FlowSysStateKind::Progress, ""), - ("存在风险", FlowSysStateKind::Progress, ""), - ("已完成", FlowSysStateKind::Progress, ""), - ("已关闭", FlowSysStateKind::Finish, ""), - ("已归档", FlowSysStateKind::Finish, ""), - ], + bind_states[0].clone(), + bind_states.clone(), "待开始-进行中-存在风险-已完成-已关闭-已归档", vec![ FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[1].clone(), name: "开始".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -418,8 +421,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -428,8 +431,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -438,8 +441,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "存在风险".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[2].clone(), name: "有风险".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -448,8 +451,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -458,8 +461,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[1].clone(), name: "正常".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -468,8 +471,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -478,8 +481,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -488,8 +491,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[1].clone(), name: "重新处理".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -498,8 +501,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -508,8 +511,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "已归档".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[5].clone(), name: "归档".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -518,8 +521,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已关闭".to_string(), - to_flow_state_name: "待开始".to_string(), + from_flow_state_id: bind_states[4].clone(), + to_flow_state_id: bind_states[0].clone(), name: "激活".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -528,8 +531,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已关闭".to_string(), - to_flow_state_name: "已归档".to_string(), + from_flow_state_id: bind_states[4].clone(), + to_flow_state_id: bind_states[5].clone(), name: "归档".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -538,8 +541,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已归档".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[5].clone(), + to_flow_state_id: bind_states[1].clone(), name: "重新激活".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -548,8 +551,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已归档".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[5].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -580,20 +583,21 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard .records .pop(); if iter_init_model.is_none() { + let mut bind_states = vec![]; + bind_states.push(FlowStateServ::init_state("ITER", "待开始", FlowSysStateKind::Start, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("ITER", "进行中", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("ITER", "存在风险", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("ITER", "已完成", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("ITER", "已关闭", FlowSysStateKind::Finish, "", funs, ctx).await?); FlowModelServ::init_model( "ITER", - vec![ - ("待开始", FlowSysStateKind::Start, ""), - ("进行中", FlowSysStateKind::Progress, ""), - ("存在风险", FlowSysStateKind::Progress, ""), - ("已完成", FlowSysStateKind::Progress, ""), - ("已关闭", FlowSysStateKind::Finish, ""), - ], + bind_states[0].clone(), + bind_states.clone(), "待开始-进行中-存在风险-已完成-已关闭", vec![ FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[1].clone(), name: "开始".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -602,8 +606,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -612,8 +616,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -622,8 +626,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "存在风险".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[2].clone(), name: "有风险".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -632,8 +636,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -642,8 +646,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[1].clone(), name: "正常".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -652,8 +656,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -662,8 +666,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -672,8 +676,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[1].clone(), name: "重新处理".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -682,8 +686,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -692,8 +696,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已关闭".to_string(), - to_flow_state_name: "待开始".to_string(), + from_flow_state_id: bind_states[4].clone(), + to_flow_state_id: bind_states[0].clone(), name: "激活".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -724,20 +728,21 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard .records .pop(); if task_init_model.is_none() { + let mut bind_states = vec![]; + bind_states.push(FlowStateServ::init_state("TASK", "待开始", FlowSysStateKind::Start, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TASK", "进行中", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TASK", "存在风险", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TASK", "已完成", FlowSysStateKind::Progress, "", funs, ctx).await?); + bind_states.push(FlowStateServ::init_state("TASK", "已关闭", FlowSysStateKind::Finish, "", funs, ctx).await?); FlowModelServ::init_model( "TASK", - vec![ - ("待开始", FlowSysStateKind::Start, ""), - ("进行中", FlowSysStateKind::Progress, ""), - ("存在风险", FlowSysStateKind::Progress, ""), - ("已完成", FlowSysStateKind::Progress, ""), - ("已关闭", FlowSysStateKind::Finish, ""), - ], + bind_states[0].clone(), + bind_states.clone(), "待开始-进行中-存在风险-已完成-已关闭", vec![ FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[1].clone(), name: "开始".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -746,8 +751,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "待开始".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[0].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -756,8 +761,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -766,8 +771,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "存在风险".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[2].clone(), name: "有风险".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -776,8 +781,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "进行中".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[1].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -786,8 +791,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[1].clone(), name: "正常".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -796,8 +801,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已完成".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[3].clone(), name: "完成".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -806,8 +811,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "存在风险".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[2].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -816,8 +821,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "进行中".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[1].clone(), name: "重新处理".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -826,8 +831,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已完成".to_string(), - to_flow_state_name: "已关闭".to_string(), + from_flow_state_id: bind_states[3].clone(), + to_flow_state_id: bind_states[4].clone(), name: "关闭".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, @@ -836,8 +841,8 @@ pub async fn init_flow_model(funs: &TardisFunsInst, ctx: &TardisContext) -> Tard ..Default::default() }, FlowTransitionInitInfo { - from_flow_state_name: "已关闭".to_string(), - to_flow_state_name: "待开始".to_string(), + from_flow_state_id: bind_states[4].clone(), + to_flow_state_id: bind_states[0].clone(), name: "激活".to_string(), double_check: Some(FlowTransitionDoubleCheckInfo { is_open: true, diff --git a/backend/middlewares/flow/src/serv/flow_model_serv.rs b/backend/middlewares/flow/src/serv/flow_model_serv.rs index 1eef7811f..f306c210d 100644 --- a/backend/middlewares/flow/src/serv/flow_model_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_model_serv.rs @@ -21,6 +21,7 @@ use tardis::{ sea_query::{Alias, Cond, Expr, Query, SelectStatement}, EntityName, EntityTrait, JoinType, Order, QueryFilter, Set, }, + futures::future::join_all, serde_json::json, web::web_resp::TardisPage, TardisFuns, TardisFunsInst, @@ -30,13 +31,12 @@ use crate::{ domain::{flow_model, flow_state, flow_transition}, dto::{ flow_model_dto::{ - FlowModelAddReq, FlowModelAggResp, FlowModelBindStateReq, FlowModelDetailResp, FlowModelFilterReq, FlowModelFindRelStateResp, FlowModelModifyReq, - FlowModelSortStatesReq, FlowModelSummaryResp, FlowModelUnbindStateReq, FlowStateAggResp, FlowTemplateModelResp, + FlowModelAddReq, FlowModelAggResp, FlowModelBindStateReq, FlowModelDetailResp, FlowModelFilterReq, FlowModelFindRelStateResp, FlowModelModifyReq, FlowModelSummaryResp, + FlowStateAggResp, FlowTemplateModelResp, }, - flow_state_dto::{FlowStateAddReq, FlowStateFilterReq, FlowStateRelModelExt, FlowSysStateKind}, + flow_state_dto::{FlowStateDetailResp, FlowStateFilterReq, FlowStateRelModelExt, FlowStateRelModelModifyReq}, flow_transition_dto::{ FlowTransitionActionChangeAgg, FlowTransitionActionChangeKind, FlowTransitionAddReq, FlowTransitionDetailResp, FlowTransitionInitInfo, FlowTransitionModifyReq, - FlowTransitionSortStatesReq, }, }, flow_config::FlowBasicInfoManager, @@ -93,6 +93,11 @@ impl RbumItemCrudOperation TardisResult<()> { + if let Some(states) = &add_req.states { + for state in states { + Self::bind_state(flow_model_id, state, funs, ctx).await?; + } + } if let Some(transitions) = &add_req.transitions { Self::add_transitions(flow_model_id, transitions, funs, ctx).await?; // check transition post action endless loop @@ -146,7 +151,52 @@ impl RbumItemCrudOperation TardisResult<()> { + let current_model = Self::get_item( + flow_model_id, + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + own_paths: Some("".to_string()), + ..Default::default() + }, + ..Default::default() + }, + funs, + ctx, + ) + .await?; + if current_model.own_paths != ctx.own_paths { + return Err(funs.err().internal_error( + "flow_model_serv", + "before_modify_item", + "The own_paths of current mode isn't the own_paths of ctx", + "404-flow-model-not-found", + )); + } + Ok(()) + } + async fn after_modify_item(flow_model_id: &str, modify_req: &mut FlowModelModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let mut refresh_model_name_by_sorted_states = false; + if let Some(bind_states) = &modify_req.bind_states { + for bind_state in bind_states { + Self::bind_state(flow_model_id, bind_state, funs, ctx).await?; + } + refresh_model_name_by_sorted_states = true; + } + if let Some(unbind_states) = &modify_req.unbind_states { + for unbind_state in unbind_states { + Self::unbind_state(flow_model_id, unbind_state, funs, ctx).await?; + } + refresh_model_name_by_sorted_states = true; + } + if let Some(modify_states) = &modify_req.modify_states { + for modify_state in modify_states { + Self::modify_rel_state_ext(flow_model_id, modify_state, funs, ctx).await?; + } + refresh_model_name_by_sorted_states = true; + } if let Some(add_transitions) = &modify_req.add_transitions { Self::add_transitions(flow_model_id, add_transitions, funs, ctx).await?; } @@ -170,6 +220,9 @@ impl RbumItemCrudOperation, + init_state_id: String, + state_ids: Vec, model_name: &str, transitions: Vec, funs: &TardisFunsInst, ctx: &TardisContext, - ) -> TardisResult<()> { - let mut states_map = HashMap::new(); - let mut init_state_id = "".to_string(); - for (state_name, sys_state, color) in states.clone() { - let state_id = FlowStateServ::add_item( - &mut FlowStateAddReq { - id_prefix: None, - name: Some(state_name.into()), - icon: None, - color: Some(color.to_string()), - sys_state, - info: None, - state_kind: None, - kind_conf: None, - template: None, - rel_state_id: None, - tags: Some(vec![tag.to_string()]), - scope_level: Some(RbumScopeLevelKind::Root), - disabled: None, - }, - funs, - ctx, - ) - .await?; - if init_state_id.is_empty() { - init_state_id = state_id.clone(); - } - states_map.insert(state_name, state_id); + ) -> TardisResult { + let mut bind_states = vec![]; + // states + for (i, state_id) in state_ids.into_iter().enumerate() { + bind_states.push(FlowModelBindStateReq { + state_id, + ext: FlowStateRelModelExt { sort: i as i64, show_btns: None }, + }); + } + // transitions + let mut add_transitions = vec![]; + for transition in transitions { + add_transitions.push(FlowTransitionAddReq::try_from(transition)?); } // add model let model_id = Self::add_item( @@ -282,9 +321,10 @@ impl FlowModelServ { rel_template_id: None, icon: None, info: None, - transitions: None, + transitions: Some(add_transitions), + states: Some(bind_states), tag: Some(tag.to_string()), - scope_level: None, + scope_level: Some(RbumScopeLevelKind::Root), disabled: None, template: true, rel_model_id: None, @@ -294,60 +334,7 @@ impl FlowModelServ { ) .await?; - // add rel - for (i, (state_name, _, _)) in states.iter().enumerate() { - let ext = FlowStateRelModelExt { - sort: i as i64, - ..Default::default() - }; - FlowRelServ::add_simple_rel( - &FlowRelKind::FlowModelState, - &model_id, - states_map.get(state_name).ok_or_else(|| funs.err().internal_error("flow_model_serv", "init_model", "to_flow_state_name is illegal", ""))?, - None, - None, - false, - false, - Some(json!(ext).to_string()), - funs, - ctx, - ) - .await?; - } - let mut add_transitions = vec![]; - for transition in transitions { - add_transitions.push(FlowTransitionAddReq { - from_flow_state_id: states_map - .get(transition.from_flow_state_name.as_str()) - .ok_or_else(|| funs.err().internal_error("flow_model_serv", "init_model", "from_flow_state_name is illegal", ""))? - .to_string(), - to_flow_state_id: states_map - .get(transition.to_flow_state_name.as_str()) - .ok_or_else(|| funs.err().internal_error("flow_model_serv", "init_model", "to_flow_state_name is illegal", ""))? - .to_string(), - name: Some(transition.name.into()), - transfer_by_auto: transition.transfer_by_auto, - transfer_by_timer: transition.transfer_by_timer, - guard_by_creator: transition.guard_by_creator, - guard_by_his_operators: transition.guard_by_his_operators, - guard_by_assigned: transition.guard_by_assigned, - guard_by_spec_account_ids: transition.guard_by_spec_account_ids, - guard_by_spec_role_ids: transition.guard_by_spec_role_ids, - guard_by_spec_org_ids: transition.guard_by_spec_org_ids, - guard_by_other_conds: transition.guard_by_other_conds, - vars_collect: transition.vars_collect, - action_by_pre_callback: transition.action_by_pre_callback, - action_by_post_callback: transition.action_by_post_callback, - action_by_post_changes: Some(transition.action_by_post_changes), - action_by_front_changes: Some(transition.action_by_front_changes), - double_check: transition.double_check, - is_notify: Some(true), - sort: transition.sort, - }); - } - Self::add_transitions(&model_id, &add_transitions, funs, ctx).await?; - - Ok(()) + Ok(model_id) } pub async fn add_transitions(flow_model_id: &str, add_req: &[FlowTransitionAddReq], funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { @@ -720,58 +707,40 @@ impl FlowModelServ { }) } - // Find model by tag and template id - pub async fn get_models(tags: Vec<&str>, template_id: Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { + // Find the specified models, or add it if it doesn't exist. + pub async fn find_or_add_models( + tags: Vec<&str>, + template_id: Option, + is_shared: bool, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult> { let global_ctx = TardisContext { own_paths: "".to_string(), ..ctx.clone() }; let mut result = HashMap::new(); - let models = if let Some(template_id) = &template_id { - // Since the default template is not bound to model, you can use global_ctx to find the association through the template_id - // 因为默认模板没有绑定模型,所以通过template_id查找模型可以使用global_ctx - FlowModelServ::paginate_items( - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, - with_sub_own_paths: true, - ..Default::default() - }, - rel_template_id: Some(template_id.clone()), - ..Default::default() - }, - 1, - 20, - None, - None, - funs, - &global_ctx, - ) - .await? - } else { - // If no template_id is passed, the real own_paths are used - FlowModelServ::paginate_items( - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - ignore_scope: true, - ..Default::default() - }, - tags: Some(tags.iter().map(|tag| tag.to_string()).collect_vec()), + let models = FlowModelServ::find_items( + &FlowModelFilterReq { + basic: RbumBasicFilterReq { + ignore_scope: true, + with_sub_own_paths: true, ..Default::default() }, - 1, - 20, - None, - None, - funs, - ctx, - ) - .await? - }; + tags: Some(tags.iter().map(|tag| tag.to_string()).collect_vec()), + rel_template_id: template_id.clone(), + ..Default::default() + }, + None, + None, + funs, + if is_shared { &global_ctx } else { ctx }, + ) + .await?; // First iterate over the models - for model in models.records { + for model in models { if tags.contains(&model.tag.as_str()) { result.insert( model.tag.clone(), @@ -788,24 +757,15 @@ impl FlowModelServ { for tag in tags { if !result.contains_key(tag) { // copy custom model - let model_id = Self::add_custom_model(tag, "", template_id.clone(), funs, ctx).await?; - let custom_model = Self::get_item( - &model_id, - &FlowModelFilterReq { - basic: RbumBasicFilterReq { ..Default::default() }, - ..Default::default() - }, - funs, - ctx, - ) - .await?; + let model_id = Self::add_custom_model(tag, None, template_id.clone(), funs, ctx).await?; + let added_model = Self::get_item(&model_id, &FlowModelFilterReq::default(), funs, ctx).await?; result.insert( tag.to_string(), FlowTemplateModelResp { - id: custom_model.id.clone(), - name: custom_model.name.clone(), - create_time: custom_model.create_time, - update_time: custom_model.update_time, + id: added_model.id.clone(), + name: added_model.name.clone(), + create_time: added_model.create_time, + update_time: added_model.update_time, }, ); } @@ -814,10 +774,16 @@ impl FlowModelServ { Ok(result) } - // add custom model by template model + // copy model by template model // rel_template_id: Associated parent template id // current_template_id: Current template id - pub async fn add_custom_model(tag: &str, parent_template_id: &str, rel_template_id: Option, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { + pub async fn add_custom_model( + tag: &str, + parent_template_id: Option, + rel_template_id: Option, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult { let current_model = Self::find_one_detail_item( &FlowModelFilterReq { basic: RbumBasicFilterReq { @@ -840,21 +806,22 @@ impl FlowModelServ { own_paths: "".to_string(), ..ctx.clone() }; - - let basic = if !parent_template_id.is_empty() { - RbumBasicFilterReq { - with_sub_own_paths: true, - ignore_scope: true, - ..Default::default() - } - } else { - RbumBasicFilterReq::default() - }; + // First, get the parent model, if the parent model does not exist, then get the default template + // 首先,获取父级model,若父级model不存在,则获取默认模板 let parent_model = if let Some(parent_model) = Self::find_one_detail_item( + // There are shared templates, so you need to ignore the permission judgment of own_path if the parent ID is passed in. + // 存在共享模板的情况,所以父级ID传入的情况下需要忽略 own_path 的权限判断 &FlowModelFilterReq { - basic, + basic: RbumBasicFilterReq { + with_sub_own_paths: parent_template_id.is_some(), + ignore_scope: parent_template_id.is_some(), + ..Default::default() + }, tags: Some(vec![tag.to_string()]), - rel_template_id: Some(parent_template_id.to_string()), + // When no parent ID is passed, indicating that the default template is directly obtained, rel_template_id is passed into the empty string + // 没有传入父级ID时,说明直接获取默认模板,则 rel_template_id 传入空字符串 + rel_template_id: Some(parent_template_id.unwrap_or_default()), + template: Some(true), ..Default::default() }, funs, @@ -888,41 +855,28 @@ impl FlowModelServ { info: Some(parent_model.info.clone()), init_state_id: parent_model.init_state_id.clone(), template: rel_template_id.is_some(), - rel_template_id, - transitions: None, + rel_template_id: rel_template_id.clone(), + transitions: Some(parent_model.transitions().into_iter().map(|trans| trans.into()).collect_vec()), + states: Some( + FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, &parent_model.id, None, None, funs, &global_ctx) + .await? + .iter() + .sorted_by_key(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default().sort) + .map(|rel| FlowModelBindStateReq { + state_id: rel.rel_id.clone(), + ext: TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default(), + }) + .collect::>(), + ), rel_model_id: Some(parent_model.id.clone()), tag: Some(parent_model.tag.clone()), - scope_level: None, + scope_level: if rel_template_id.is_some() { Some(RbumScopeLevelKind::Root) } else { None }, disabled: Some(parent_model.disabled), }, funs, ctx, ) .await?; - // bind states - let states = FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, &parent_model.id, None, None, funs, &global_ctx) - .await? - .iter() - .sorted_by_key(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default().sort) - .map(|rel| (rel.rel_id.clone(), TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default())) - .collect::>(); - for (state_id, ext) in states.iter() { - FlowRelServ::add_simple_rel( - &FlowRelKind::FlowModelState, - &model_id, - state_id, - None, - None, - false, - true, - Some(json!(ext).to_string()), - funs, - ctx, - ) - .await?; - } - // add transition - Self::add_transitions(&model_id, &parent_model.transitions().into_iter().map(|trans| trans.into()).collect_vec(), funs, ctx).await?; Ok(model_id) } @@ -948,55 +902,37 @@ impl FlowModelServ { Ok(()) } - pub async fn bind_state(flow_rel_kind: &FlowRelKind, flow_model_id: &str, req: &FlowModelBindStateReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let flow_state_id = &req.state_id; - if FlowStateServ::get_item(flow_state_id, &FlowStateFilterReq::default(), funs, ctx).await.is_err() { - return Err(funs.err().internal_error("flow_model_serv", "bind_state", "The flow state is not found", "404-flow-state-not-found")); - } - let sort = req.sort; - let current_model = Self::get_item( - flow_model_id, - &FlowModelFilterReq { + pub async fn bind_state(flow_model_id: &str, req: &FlowModelBindStateReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + let global_ctx = TardisContext { + own_paths: "".to_string(), + ..ctx.clone() + }; + if FlowStateServ::get_item( + &req.state_id, + &FlowStateFilterReq { basic: RbumBasicFilterReq { with_sub_own_paths: true, - own_paths: Some("".to_string()), ..Default::default() }, ..Default::default() }, funs, - ctx, + &global_ctx, ) - .await?; - if current_model.own_paths != ctx.own_paths { - return Err(funs.err().internal_error( - "flow_model_serv", - "bind_state", - "The own_paths of current mode isn't the own_paths of ctx", - "404-flow-model-not-found", - )); + .await + .is_err() + { + return Err(funs.err().internal_error("flow_model_serv", "bind_state", "The flow state is not found", "404-flow-state-not-found")); } - let ext = FlowStateRelModelExt { sort, ..Default::default() }; FlowRelServ::add_simple_rel( - flow_rel_kind, + &FlowRelKind::FlowModelState, flow_model_id, - flow_state_id, + &req.state_id, None, None, false, true, - Some(json!(ext).to_string()), - funs, - ctx, - ) - .await?; - - Self::modify_item( - flow_model_id, - &mut FlowModelModifyReq { - name: Some(Self::get_model_name(flow_model_id, funs, ctx).await?.into()), - ..Default::default() - }, + Some(json!(req.ext).to_string()), funs, ctx, ) @@ -1005,122 +941,45 @@ impl FlowModelServ { Ok(()) } - pub async fn unbind_state(flow_rel_kind: &FlowRelKind, flow_model_id: &str, req: &FlowModelUnbindStateReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let flow_state_id = &req.state_id; + pub async fn unbind_state(flow_model_id: &str, state_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { // Can only be deleted when not in use - if FlowInstServ::state_is_used(flow_model_id, flow_state_id, funs, ctx).await? { + if FlowInstServ::state_is_used(flow_model_id, state_id, funs, ctx).await? { return Err(funs.err().conflict( &Self::get_obj_name(), "unbind_state", - &format!("state {flow_state_id} already used"), + &format!("state {state_id} already used"), "409-flow-state-already-used", )); } - let current_model = Self::get_item( - flow_model_id, - &FlowModelFilterReq { - basic: RbumBasicFilterReq { - with_sub_own_paths: true, - own_paths: Some("".to_string()), - ..Default::default() - }, - ..Default::default() - }, - funs, - ctx, - ) - .await?; - if current_model.own_paths != ctx.own_paths { - return Err(funs.err().internal_error( - "flow_model_serv", - "unbind_state", - "The own_paths of current mode isn't the own_paths of ctx", - "404-flow-model-not-found", - )); - } - FlowRelServ::delete_simple_rel(flow_rel_kind, flow_model_id, flow_state_id, funs, ctx).await?; - - //delete transitions - let trans_ids = - Self::find_transitions_by_state_id(flow_model_id, Some(vec![flow_state_id.to_string()]), None, funs, ctx).await?.into_iter().map(|trans| trans.id).collect_vec(); + //delete rel transitions + let trans_ids = Self::find_transitions_by_state_id(flow_model_id, Some(vec![state_id.to_string()]), None, funs, ctx).await?.into_iter().map(|trans| trans.id).collect_vec(); Self::delete_transitions(flow_model_id, &trans_ids, funs, ctx).await?; - let trans_ids = - Self::find_transitions_by_state_id(flow_model_id, None, Some(vec![flow_state_id.to_string()]), funs, ctx).await?.into_iter().map(|trans| trans.id).collect_vec(); + let trans_ids = Self::find_transitions_by_state_id(flow_model_id, None, Some(vec![state_id.to_string()]), funs, ctx).await?.into_iter().map(|trans| trans.id).collect_vec(); Self::delete_transitions(flow_model_id, &trans_ids, funs, ctx).await?; - Self::modify_item( - flow_model_id, - &mut FlowModelModifyReq { - name: Some(Self::get_model_name(flow_model_id, funs, ctx).await?.into()), - ..Default::default() - }, - funs, - ctx, - ) - .await?; + FlowRelServ::delete_simple_rel(&FlowRelKind::FlowModelState, flow_model_id, state_id, funs, ctx).await?; Ok(()) } - pub async fn resort_state(flow_rel_kind: &FlowRelKind, flow_model_id: &str, sort_req: &FlowModelSortStatesReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - let sort_states = &sort_req.sort_states; - let states = FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, flow_model_id, None, None, funs, ctx).await?; - for sort_state in sort_states { - let show_btns = TardisFuns::json - .str_to_obj::( - &states - .iter() - .find(|state| state.rel_id == sort_state.state_id) - .ok_or_else(|| funs.err().internal_error("flow_model_serv", "resort_state", "rel not found", "404-rel-not-found"))? - .ext, - ) - .unwrap_or_default() - .show_btns; - let ext = FlowStateRelModelExt { sort: sort_state.sort, show_btns }; - FlowRelServ::modify_simple_rel( - flow_rel_kind, - flow_model_id, - &sort_state.state_id, - &mut RbumRelModifyReq { - tag: None, - note: None, - ext: Some(json!(ext).to_string()), - }, - funs, - ctx, - ) - .await?; - } - Self::modify_item( - flow_model_id, - &mut FlowModelModifyReq { - name: Some(Self::get_model_name(flow_model_id, funs, ctx).await?.into()), - ..Default::default() - }, - funs, - ctx, - ) - .await?; - - Ok(()) - } - - pub async fn modify_rel_state(flow_model_id: &str, state_id: &str, new_ext: &FlowStateRelModelExt, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + pub async fn modify_rel_state_ext(flow_model_id: &str, modify_req: &FlowStateRelModelModifyReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { let mut ext = TardisFuns::json.str_to_obj::( - &FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, flow_model_id, None, None, funs, ctx) + &FlowRelServ::find_simple_rels(&FlowRelKind::FlowModelState, Some(flow_model_id), Some(modify_req.id.as_str()), true, None, None, funs, ctx) .await? - .into_iter() - .find(|rel| rel.rel_id == state_id) + .pop() .ok_or_else(|| funs.err().internal_error("flow_model_serv", "modify_rel_state", "rel not found", "404-rel-not-found"))? .ext, )?; - if let Some(show_btns) = new_ext.show_btns.clone() { + if let Some(sort) = modify_req.sort { + ext.sort = sort; + } + if let Some(show_btns) = modify_req.show_btns.clone() { ext.show_btns = Some(show_btns); } FlowRelServ::modify_simple_rel( &FlowRelKind::FlowModelState, flow_model_id, - state_id, + &modify_req.id, &mut RbumRelModifyReq { tag: None, note: None, @@ -1134,40 +993,6 @@ impl FlowModelServ { Ok(()) } - pub async fn resort_transition(flow_model_id: &str, sort_req: &FlowTransitionSortStatesReq, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { - // @TODO wait tardis updated - let modify_trans = sort_req - .sort_states - .iter() - .map(|sort_req| FlowTransitionModifyReq { - id: sort_req.id.clone().into(), - name: None, - from_flow_state_id: None, - to_flow_state_id: None, - transfer_by_auto: None, - transfer_by_timer: None, - guard_by_creator: None, - guard_by_his_operators: None, - guard_by_assigned: None, - guard_by_spec_account_ids: None, - guard_by_spec_role_ids: None, - guard_by_spec_org_ids: None, - guard_by_other_conds: None, - vars_collect: None, - double_check: None, - is_notify: None, - action_by_pre_callback: None, - action_by_post_callback: None, - action_by_post_changes: None, - action_by_front_changes: None, - sort: Some(sort_req.sort), - }) - .collect_vec(); - Self::modify_transitions(flow_model_id, &modify_trans, funs, ctx).await?; - - Ok(()) - } - async fn find_transitions_by_state_id( flow_model_id: &str, current_state_id: Option>, @@ -1280,45 +1105,60 @@ impl FlowModelServ { let mut result = Vec::new(); for tag in tags { let flow_model_id = FlowInstServ::get_model_id_by_own_paths_and_rel_template_id(tag, rel_template_id.clone(), funs, ctx).await?; - let mut states = Self::find_sorted_rel_states_by_model_id(&flow_model_id, funs, ctx).await?; + let mut states = Self::find_sorted_rel_states_by_model_id(&flow_model_id, funs, ctx) + .await? + .into_iter() + .map(|state_detail| FlowModelFindRelStateResp { + id: state_detail.id.clone(), + name: state_detail.name.clone(), + color: state_detail.color.clone(), + }) + .collect_vec(); result.append(&mut states); } Ok(result) } - async fn find_sorted_rel_states_by_model_id(flow_model_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { - let state_ids = FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, flow_model_id, None, None, funs, ctx) - .await? - .iter() - .sorted_by_key(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default().sort) - .map(|rel| rel.rel_id.clone()) - .collect::>(); - Ok(FlowStateServ::find_detail_items( - &FlowStateFilterReq { - basic: RbumBasicFilterReq { - ids: Some(state_ids), - with_sub_own_paths: true, - own_paths: Some("".to_string()), - ..Default::default() - }, + async fn find_sorted_rel_states_by_model_id(flow_model_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult> { + Ok(join_all( + FlowRelServ::find_from_simple_rels(&FlowRelKind::FlowModelState, flow_model_id, None, None, funs, ctx) + .await? + .into_iter() + .sorted_by_key(|rel| TardisFuns::json.str_to_obj::(&rel.ext).unwrap_or_default().sort) + .map(|rel| async move { + FlowStateServ::find_one_detail_item( + &FlowStateFilterReq { + basic: RbumBasicFilterReq { + ids: Some(vec![rel.rel_id]), + with_sub_own_paths: true, + own_paths: Some("".to_string()), + ..Default::default() + }, + ..Default::default() + }, + funs, + ctx, + ) + .await + .unwrap_or_default() + .unwrap() + }) + .collect::>(), + ) + .await) + } + + async fn refresh_model_name_by_sorted_states(flow_model_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult<()> { + Self::modify_item( + flow_model_id, + &mut FlowModelModifyReq { + name: Some(Self::find_sorted_rel_states_by_model_id(flow_model_id, funs, ctx).await?.into_iter().map(|state| state.name).collect_vec().join("-").into()), ..Default::default() }, - None, - Some(true), funs, ctx, ) - .await? - .iter() - .map(|state_detail| FlowModelFindRelStateResp { - id: state_detail.id.clone(), - name: state_detail.name.clone(), - color: state_detail.color.clone(), - }) - .collect_vec()) - } - - async fn get_model_name(flow_model_id: &str, funs: &TardisFunsInst, ctx: &TardisContext) -> TardisResult { - Ok(Self::find_sorted_rel_states_by_model_id(flow_model_id, funs, ctx).await?.into_iter().map(|state| state.name).collect_vec().join("-")) + .await?; + Ok(()) } } diff --git a/backend/middlewares/flow/src/serv/flow_rel_serv.rs b/backend/middlewares/flow/src/serv/flow_rel_serv.rs index c23eaf363..002731623 100644 --- a/backend/middlewares/flow/src/serv/flow_rel_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_rel_serv.rs @@ -159,6 +159,39 @@ impl FlowRelServ { .await } + pub async fn find_simple_rels( + flow_rel_kind: &FlowRelKind, + flow_model_id: Option<&str>, + flow_state_id: Option<&str>, + is_from: bool, + desc_sort_by_create: Option, + desc_sort_by_update: Option, + funs: &TardisFunsInst, + ctx: &TardisContext, + ) -> TardisResult> { + let mock_ctx = TardisContext { + own_paths: "".to_string(), + ..ctx.clone() + }; + let mut filter_req = RbumRelFilterReq { + basic: RbumBasicFilterReq { + with_sub_own_paths: true, + ..Default::default() + }, + tag: Some(flow_rel_kind.to_string()), + ..Default::default() + }; + if flow_model_id.is_some() { + filter_req.from_rbum_kind = Some(RbumRelFromKind::Item); + filter_req.from_rbum_id = flow_model_id.map(|s| s.to_string()); + } + if flow_state_id.is_some() { + filter_req.to_rbum_item_id = flow_state_id.map(|s| s.to_string()); + } + + RbumRelServ::find_simple_rels(&filter_req, desc_sort_by_create, desc_sort_by_update, is_from, funs, &mock_ctx).await + } + pub async fn modify_simple_rel( flow_rel_kind: &FlowRelKind, flow_model_id: &str, diff --git a/backend/middlewares/flow/src/serv/flow_state_serv.rs b/backend/middlewares/flow/src/serv/flow_state_serv.rs index 33489f1ff..43219740c 100644 --- a/backend/middlewares/flow/src/serv/flow_state_serv.rs +++ b/backend/middlewares/flow/src/serv/flow_state_serv.rs @@ -6,6 +6,7 @@ use bios_basic::rbum::{ rbum_item_dto::{RbumItemKernelAddReq, RbumItemKernelModifyReq}, }, helper::rbum_scope_helper, + rbum_enumeration::RbumScopeLevelKind, serv::rbum_item_serv::RbumItemCrudOperation, }; use itertools::Itertools; @@ -25,7 +26,7 @@ use crate::{ flow_model_dto::FlowModelFilterReq, flow_state_dto::{ FlowStateAddReq, FlowStateCountGroupByStateReq, FlowStateCountGroupByStateResp, FlowStateDetailResp, FlowStateFilterReq, FlowStateKind, FlowStateModifyReq, - FlowStateNameResp, FlowStateSummaryResp, + FlowStateNameResp, FlowStateSummaryResp, FlowSysStateKind, }, }, flow_config::FlowBasicInfoManager, @@ -215,6 +216,28 @@ impl RbumItemCrudOperation TardisResult { + FlowStateServ::add_item( + &mut FlowStateAddReq { + id_prefix: None, + name: Some(state_name.into()), + icon: None, + color: Some(color.to_string()), + sys_state, + info: None, + state_kind: None, + kind_conf: None, + template: None, + rel_state_id: None, + tags: Some(vec![tag.to_string()]), + scope_level: Some(RbumScopeLevelKind::Root), + disabled: None, + }, + funs, + ctx, + ) + .await + } pub(crate) async fn find_names( ids: Option>, tag: Option, @@ -322,11 +345,6 @@ impl FlowStateServ { count: inst_ids.len().to_string(), inst_ids, }); - // result.push(FlowStateCountGroupByStateResp { - // state_name, - // count: inst_ids.len().to_string(), - // inst_ids, - // }); } Ok(result.into_values().collect_vec()) } diff --git a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs index 49d69e7a5..a040ccd65 100644 --- a/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs +++ b/backend/middlewares/flow/tests/test_flow_scenes_fsm.rs @@ -12,7 +12,7 @@ use bios_mw_flow::dto::flow_model_dto::{ FlowModelAddCustomModelItemReq, FlowModelAddCustomModelReq, FlowModelAddCustomModelResp, FlowModelAggResp, FlowModelBindStateReq, FlowModelFindRelStateResp, FlowModelModifyReq, FlowModelSortStateInfoReq, FlowModelSortStatesReq, FlowModelSummaryResp, FlowModelUnbindStateReq, FlowTemplateModelResp, }; -use bios_mw_flow::dto::flow_state_dto::{FlowStateAddReq, FlowStateSummaryResp, FlowSysStateKind}; +use bios_mw_flow::dto::flow_state_dto::{FlowStateAddReq, FlowStateRelModelExt, FlowStateSummaryResp, FlowSysStateKind}; use bios_mw_flow::dto::flow_transition_dto::{ FlowTransitionActionByVarChangeInfoChangedKind, FlowTransitionActionChangeInfo, FlowTransitionActionChangeKind, FlowTransitionAddReq, FlowTransitionDoubleCheckInfo, FlowTransitionModifyReq, FlowTransitionSortStateInfoReq, FlowTransitionSortStatesReq, StateChangeCondition, StateChangeConditionItem, StateChangeConditionOp, @@ -149,7 +149,12 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { let mock_template_id = "mock_template_id".to_string(); // 2-2. create flow models by template_id - let result: HashMap = flow_client.get(&format!("/cc/model/get_models?tag_ids=REQ,TICKET,ITER,PROJ&temp_id={}", mock_template_id)).await; + let result: HashMap = flow_client + .put( + &format!("/cc/model/find_or_add_models?tag_ids=REQ,TICKET,ITER,PROJ&is_shared=true&temp_id={}", mock_template_id), + &json!(""), + ) + .await; let req_model_id = result.get("REQ").unwrap().id.clone(); let req_model_agg: FlowModelAggResp = flow_client.get(&format!("/cc/model/{}", req_model_id)).await; let ticket_model_id = result.get("TICKET").unwrap().id.clone(); @@ -455,7 +460,12 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { ) .await; let share_template_id = "share_template_id".to_string(); - let share_template_models: HashMap = flow_client.get(&format!("/cc/model/get_models?tag_ids=REQ&temp_id={}", share_template_id)).await; + let share_template_models: HashMap = flow_client + .put( + &format!("/cc/model/find_or_add_models?tag_ids=REQ&is_shared=true&temp_id={}", share_template_id), + &json!(""), + ) + .await; let req_share_model_id = share_template_models.get("REQ").unwrap().id.clone(); let req_share_model_agg: FlowModelAggResp = flow_client.get(&format!("/cc/model/{}", req_share_model_id)).await; let _: Void = flow_client @@ -463,7 +473,7 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { &format!("/cc/model/{}/bind_state", &req_share_model_id), &FlowModelBindStateReq { state_id: custom_state_id.clone(), - sort: 1, + ext: FlowStateRelModelExt { sort: 1, show_btns: None }, }, ) .await; @@ -479,7 +489,12 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { ctx.own_paths = "t2".to_string(); flow_client.set_auth(&ctx)?; - let other_models: HashMap = flow_client.get(&format!("/cc/model/get_models?tag_ids=REQ&temp_id={}", share_template_id)).await; + let other_models: HashMap = flow_client + .put( + &format!("/cc/model/find_or_add_models?tag_ids=REQ&is_shared=true&temp_id={}", share_template_id), + &json!(""), + ) + .await; assert_eq!(req_share_model_id, other_models.get("REQ").unwrap().id.clone()); ctx.own_paths = "t3/app03".to_string(); @@ -511,7 +526,7 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { }, ) .await; - let share_template_models: HashMap = flow_client.get("/cc/model/get_models?tag_ids=REQ").await; + let share_template_models: HashMap = flow_client.put("/cc/model/find_or_add_models?tag_ids=REQ", &json!("")).await; assert_eq!(share_model_id.as_str(), share_template_models.get("REQ").unwrap().id.as_str()); let share_model_agg: FlowModelAggResp = flow_client.get(&format!("/cc/model/{}", share_model_id)).await; @@ -559,11 +574,11 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { &format!("/cc/model/{}/bind_state", &share_model_id), &FlowModelBindStateReq { state_id: custom_state_id.clone(), - sort: 1, + ext: FlowStateRelModelExt { sort: 1, show_btns: None }, }, ) .await; - assert_eq!(state_bind_error.code, "500-flow-flow_model_serv-bind_state"); + assert_eq!(state_bind_error.code, "409-flow-FlowModelState-add_simple_rel"); // reset share model ctx.own_paths = "t1".to_string(); flow_client.set_auth(&ctx)?; @@ -598,7 +613,8 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { }, ) .await; - let models: HashMap = flow_client.get("/cc/model/get_models?tag_ids=REQ,PROJ,ITER,TICKET").await; + let models: HashMap = flow_client.put("/cc/model/find_or_add_models?tag_ids=REQ,PROJ,ITER,TICKET", &json!("")).await; + let req_model_id_app = &models.get("REQ").unwrap().id; assert_eq!( models.get("REQ").unwrap().id, result.into_iter().find(|model| model.tag == "REQ").unwrap().model_id.unwrap() @@ -711,13 +727,13 @@ pub async fn test(flow_client: &mut TestHttpClient) -> TardisResult<()> { // check state is used let state_unbind_error = flow_client .post_resp::( - &format!("/cc/model/{}/unbind_state", &req_model_id), + &format!("/cc/model/{}/unbind_state", &req_model_id_app), &FlowModelUnbindStateReq { state_id: transfer.new_flow_state_id.clone(), }, ) .await; - assert_eq!(state_unbind_error.code, "500-flow-flow_model_serv-unbind_state"); + assert_eq!(state_unbind_error.code, "409-flow-flow_model-unbind_state"); // 6. post action // check original instance let ticket: FlowInstDetailResp = flow_client.get(&format!("/cc/inst/{}", ticket_inst_id)).await;