sz_rust_workflow/definition/
strategy.rs1use serde::{Deserialize, Serialize};
5
6#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
8#[serde(tag = "type", rename_all = "snake_case")]
9pub enum CandidateStrategy {
10 Static {
12 #[serde(default)]
13 users: Vec<String>,
14 #[serde(default)]
15 roles: Vec<String>,
16 },
17 Dynamic { expr: String },
19 Capability {
21 capability_name: String,
22 #[serde(default)]
23 args: serde_json::Value,
24 },
25}
26
27#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
29#[serde(rename_all = "snake_case")]
30pub enum ApprovalStrategyType {
31 #[default]
33 AndSign,
34 OrSign,
36}
37
38#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Serialize, Deserialize, Default)]
40#[serde(rename_all = "snake_case")]
41pub enum FaultStrategy {
42 #[default]
44 Fail,
45 Skip,
47 Retry,
49}
50
51#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
53pub struct Transition {
54 pub from: String,
56 pub to: String,
58 pub event: String,
60 #[serde(default, skip_serializing_if = "Option::is_none")]
62 pub guard: Option<String>,
63}
64
65#[cfg(test)]
66mod tests {
67 use super::*;
68
69 #[test]
70 fn candidate_strategy_static_serde() {
71 let s = CandidateStrategy::Static {
72 users: vec!["u1".into()],
73 roles: vec!["admin".into()],
74 };
75 let json = serde_json::to_string(&s).unwrap();
76 let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
77 assert_eq!(s, back);
78 }
79
80 #[test]
81 fn candidate_strategy_dynamic_serde() {
82 let s = CandidateStrategy::Dynamic {
83 expr: "$.candidates".into(),
84 };
85 let json = serde_json::to_string(&s).unwrap();
86 assert!(json.contains("\"type\":\"dynamic\""));
87 let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
88 assert_eq!(s, back);
89 }
90
91 #[test]
92 fn candidate_strategy_capability_serde() {
93 let s = CandidateStrategy::Capability {
94 capability_name: "hr.get_managers".into(),
95 args: serde_json::json!({"dept": "tech"}),
96 };
97 let json = serde_json::to_string(&s).unwrap();
98 let back: CandidateStrategy = serde_json::from_str(&json).unwrap();
99 assert_eq!(s, back);
100 }
101
102 #[test]
103 fn approval_strategy_type_serde() {
104 let json = serde_json::to_string(&ApprovalStrategyType::AndSign).unwrap();
105 assert_eq!(json, "\"and_sign\"");
106 let json = serde_json::to_string(&ApprovalStrategyType::OrSign).unwrap();
107 assert_eq!(json, "\"or_sign\"");
108 }
109
110 #[test]
111 fn fault_strategy_serde() {
112 assert_eq!(
113 serde_json::to_string(&FaultStrategy::Fail).unwrap(),
114 "\"fail\""
115 );
116 assert_eq!(
117 serde_json::to_string(&FaultStrategy::Skip).unwrap(),
118 "\"skip\""
119 );
120 assert_eq!(
121 serde_json::to_string(&FaultStrategy::Retry).unwrap(),
122 "\"retry\""
123 );
124 }
125
126 #[test]
127 fn transition_serde() {
128 let t = Transition {
129 from: "draft".into(),
130 to: "review".into(),
131 event: "submit".into(),
132 guard: Some("$.amount > 100".into()),
133 };
134 let json = serde_json::to_string(&t).unwrap();
135 let back: Transition = serde_json::from_str(&json).unwrap();
136 assert_eq!(t, back);
137
138 let t2 = Transition {
139 from: "draft".into(),
140 to: "review".into(),
141 event: "submit".into(),
142 guard: None,
143 };
144 let json2 = serde_json::to_string(&t2).unwrap();
145 assert!(!json2.contains("guard"));
146 }
147}