sz_configtool_lib/calls/
standardize.rs1use crate::error::{Result, SzConfigError};
7use crate::helpers::{
8 find_in_config_array, get_next_id, lookup_element_id, lookup_feature_id, lookup_sfunc_id,
9};
10use serde_json::{Value, json};
11
12#[derive(Debug, Clone)]
18pub struct AddStandardizeCallParams<'a> {
19 pub ftype_code: Option<&'a str>,
20 pub felem_code: Option<&'a str>,
21 pub exec_order: Option<i64>,
22 pub sfunc_code: &'a str,
23}
24
25impl<'a> AddStandardizeCallParams<'a> {
26 pub fn new(sfunc_code: &'a str) -> Self {
27 Self {
28 ftype_code: None,
29 felem_code: None,
30 exec_order: None,
31 sfunc_code,
32 }
33 }
34}
35
36#[derive(Debug, Clone)]
38pub struct AddStandardizeCallElementParams {
39 pub ftype_id: i64,
40 pub sfunc_id: i64,
41 pub felem_id: Option<i64>,
42 pub exec_order: Option<i64>,
43}
44
45#[derive(Debug, Clone, Default)]
47pub struct SetStandardizeCallParams {
48 pub sfcall_id: i64,
49 pub exec_order: Option<i64>,
50}
51
52impl TryFrom<&Value> for SetStandardizeCallParams {
53 type Error = SzConfigError;
54
55 fn try_from(json: &Value) -> Result<Self> {
56 let sfcall_id = json
57 .get("sfcallId")
58 .and_then(|v| v.as_i64())
59 .ok_or_else(|| SzConfigError::MissingField("sfcallId".to_string()))?;
60
61 Ok(Self {
62 sfcall_id,
63 exec_order: json.get("execOrder").and_then(|v| v.as_i64()),
64 })
65 }
66}
67
68#[derive(Debug, Clone)]
70pub struct DeleteStandardizeCallElementParams {
71 pub ftype_id: i64,
72 pub sfunc_id: i64,
73 pub felem_id: Option<i64>,
74}
75
76#[derive(Debug, Clone)]
78pub struct SetStandardizeCallElementParams {
79 pub ftype_id: i64,
80 pub sfunc_id: i64,
81 pub felem_id: Option<i64>,
82 pub updates: Value,
83}
84
85pub fn add_standardize_call(
102 config: &str,
103 params: AddStandardizeCallParams,
104) -> Result<(String, Value)> {
105 let mut config_data: Value =
106 serde_json::from_str(config).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
107
108 let sfcall_id = get_next_id(&config_data, "G2_CONFIG.CFG_SFCALL", "SFCALL_ID", 1000)?;
110
111 let sfunc_id = lookup_sfunc_id(config, params.sfunc_code)?;
113
114 let mut ftype_id: i64 = -1;
116 let mut felem_id: i64 = -1;
117
118 if let Some(feature) = params.ftype_code.filter(|f| !f.eq_ignore_ascii_case("ALL")) {
119 ftype_id = lookup_feature_id(config, feature)?;
120 }
121
122 if let Some(element) = params.felem_code.filter(|e| !e.eq_ignore_ascii_case("N/A")) {
123 felem_id = lookup_element_id(config, element)?;
124 }
125
126 if (ftype_id > 0 && felem_id > 0) || (ftype_id < 0 && felem_id < 0) {
128 return Err(SzConfigError::InvalidInput(
129 "Either a feature or an element must be specified, but not both".to_string(),
130 ));
131 }
132
133 let final_exec_order = if let Some(order) = params.exec_order {
135 let order_taken = config_data["G2_CONFIG"]["CFG_SFCALL"]
137 .as_array()
138 .map(|arr| {
139 arr.iter().any(|call| {
140 call["FTYPE_ID"].as_i64() == Some(ftype_id)
141 && call["FELEM_ID"].as_i64() == Some(felem_id)
142 && call["EXEC_ORDER"].as_i64() == Some(order)
143 })
144 })
145 .unwrap_or(false);
146
147 if order_taken {
148 return Err(SzConfigError::AlreadyExists(format!(
149 "Execution order {order} already taken for this feature/element"
150 )));
151 }
152 order
153 } else {
154 config_data["G2_CONFIG"]["CFG_SFCALL"]
156 .as_array()
157 .map(|arr| {
158 arr.iter()
159 .filter(|call| {
160 call["FTYPE_ID"].as_i64() == Some(ftype_id)
161 && call["FELEM_ID"].as_i64() == Some(felem_id)
162 })
163 .filter_map(|call| call["EXEC_ORDER"].as_i64())
164 .max()
165 .map(|max| max + 1)
166 .unwrap_or(1)
167 })
168 .unwrap_or(1)
169 };
170
171 let new_record = json!({
173 "SFCALL_ID": sfcall_id,
174 "FTYPE_ID": ftype_id,
175 "FELEM_ID": felem_id,
176 "SFUNC_ID": sfunc_id,
177 "EXEC_ORDER": final_exec_order
178 });
179
180 if let Some(sfcall_array) = config_data["G2_CONFIG"]["CFG_SFCALL"].as_array_mut() {
182 sfcall_array.push(new_record.clone());
183 } else {
184 return Err(SzConfigError::MissingSection("CFG_SFCALL".to_string()));
185 }
186
187 let modified_config =
188 serde_json::to_string(&config_data).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
189
190 Ok((modified_config, new_record))
191}
192
193pub fn delete_standardize_call(config: &str, sfcall_id: i64) -> Result<String> {
205 let mut config_data: Value =
206 serde_json::from_str(config).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
207
208 let call_exists = config_data["G2_CONFIG"]["CFG_SFCALL"]
210 .as_array()
211 .map(|arr| {
212 arr.iter()
213 .any(|call| call["SFCALL_ID"].as_i64() == Some(sfcall_id))
214 })
215 .unwrap_or(false);
216
217 if !call_exists {
218 return Err(SzConfigError::NotFound(format!(
219 "Standardize call ID {sfcall_id}"
220 )));
221 }
222
223 if let Some(sfcall_array) = config_data["G2_CONFIG"]["CFG_SFCALL"].as_array_mut() {
225 sfcall_array.retain(|record| record["SFCALL_ID"].as_i64() != Some(sfcall_id));
226 }
227
228 serde_json::to_string(&config_data).map_err(|e| SzConfigError::JsonParse(e.to_string()))
229}
230
231pub fn get_standardize_call(config: &str, sfcall_id: i64) -> Result<Value> {
243 find_in_config_array(config, "CFG_SFCALL", "SFCALL_ID", &sfcall_id.to_string())?
244 .ok_or_else(|| SzConfigError::NotFound(format!("Standardize call ID {sfcall_id}")))
245}
246
247pub fn list_standardize_calls(config: &str) -> Result<Vec<Value>> {
257 let config_data: Value =
258 serde_json::from_str(config).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
259
260 let empty_array = vec![];
261 let sfcall_array = config_data
262 .get("G2_CONFIG")
263 .and_then(|g| g.get("CFG_SFCALL"))
264 .and_then(|v| v.as_array())
265 .unwrap_or(&empty_array);
266
267 let ftype_array = config_data
268 .get("G2_CONFIG")
269 .and_then(|g| g.get("CFG_FTYPE"))
270 .and_then(|v| v.as_array())
271 .unwrap_or(&empty_array);
272
273 let felem_array = config_data
274 .get("G2_CONFIG")
275 .and_then(|g| g.get("CFG_FELEM"))
276 .and_then(|v| v.as_array())
277 .unwrap_or(&empty_array);
278
279 let sfunc_array = config_data
280 .get("G2_CONFIG")
281 .and_then(|g| g.get("CFG_SFUNC"))
282 .and_then(|v| v.as_array())
283 .unwrap_or(&empty_array);
284
285 let resolve_ftype = |ftype_id: i64| -> String {
287 if ftype_id <= 0 {
288 "all".to_string()
289 } else {
290 ftype_array
291 .iter()
292 .find(|ft| ft.get("FTYPE_ID").and_then(|v| v.as_i64()) == Some(ftype_id))
293 .and_then(|ft| ft.get("FTYPE_CODE"))
294 .and_then(|v| v.as_str())
295 .unwrap_or("all")
296 .to_string()
297 }
298 };
299
300 let resolve_felem = |felem_id: i64| -> String {
301 if felem_id <= 0 {
302 "n/a".to_string()
303 } else {
304 felem_array
305 .iter()
306 .find(|fe| fe.get("FELEM_ID").and_then(|v| v.as_i64()) == Some(felem_id))
307 .and_then(|fe| fe.get("FELEM_CODE"))
308 .and_then(|v| v.as_str())
309 .unwrap_or("n/a")
310 .to_string()
311 }
312 };
313
314 let resolve_sfunc = |sfunc_id: i64| -> String {
315 sfunc_array
316 .iter()
317 .find(|sf| sf.get("SFUNC_ID").and_then(|v| v.as_i64()) == Some(sfunc_id))
318 .and_then(|sf| sf.get("SFUNC_CODE"))
319 .and_then(|v| v.as_str())
320 .unwrap_or("unknown")
321 .to_string()
322 };
323
324 let items: Vec<Value> = sfcall_array
326 .iter()
327 .map(|item| {
328 let ftype_id = item.get("FTYPE_ID").and_then(|v| v.as_i64()).unwrap_or(0);
329 let felem_id = item.get("FELEM_ID").and_then(|v| v.as_i64()).unwrap_or(0);
330 let sfunc_id = item.get("SFUNC_ID").and_then(|v| v.as_i64()).unwrap_or(0);
331
332 json!({
333 "id": item.get("SFCALL_ID").and_then(|v| v.as_i64()).unwrap_or(0),
334 "feature": resolve_ftype(ftype_id),
335 "element": resolve_felem(felem_id),
336 "execOrder": item.get("EXEC_ORDER").and_then(|v| v.as_i64()).unwrap_or(0),
337 "function": resolve_sfunc(sfunc_id)
338 })
339 })
340 .collect();
341
342 Ok(items)
343}
344
345pub fn set_standardize_call(config: &str, _params: SetStandardizeCallParams) -> Result<String> {
354 Ok(config.to_string())
356}
357
358pub fn add_standardize_call_element(
369 config: &str,
370 params: AddStandardizeCallElementParams,
371) -> Result<(String, Value)> {
372 let mut config_data: Value =
373 serde_json::from_str(config).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
374
375 let final_felem_id = params.felem_id.unwrap_or(-1);
376
377 if let Some(sfcall_array) = config_data
379 .get("G2_CONFIG")
380 .and_then(|g| g.get("CFG_SFCALL"))
381 .and_then(|v| v.as_array())
382 {
383 for item in sfcall_array {
384 if item.get("FTYPE_ID").and_then(|v| v.as_i64()) == Some(params.ftype_id)
385 && item.get("SFUNC_ID").and_then(|v| v.as_i64()) == Some(params.sfunc_id)
386 && item.get("FELEM_ID").and_then(|v| v.as_i64()) == Some(final_felem_id)
387 {
388 return Err(SzConfigError::AlreadyExists(
389 "Standardize call element already exists".to_string(),
390 ));
391 }
392 }
393 }
394
395 let sfcall_id = get_next_id(&config_data, "G2_CONFIG.CFG_SFCALL", "SFCALL_ID", 1000)?;
397
398 let mut new_record = json!({
400 "SFCALL_ID": sfcall_id,
401 "FTYPE_ID": params.ftype_id,
402 "FELEM_ID": final_felem_id,
403 "SFUNC_ID": params.sfunc_id,
404 });
405
406 new_record["EXEC_ORDER"] = match params.exec_order {
408 Some(order) => json!(order),
409 None => Value::Null,
410 };
411
412 if let Some(sfcall_array) = config_data["G2_CONFIG"]["CFG_SFCALL"].as_array_mut() {
414 sfcall_array.push(new_record.clone());
415 } else {
416 return Err(SzConfigError::MissingSection("CFG_SFCALL".to_string()));
417 }
418
419 let modified_config =
420 serde_json::to_string(&config_data).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
421
422 Ok((modified_config, new_record))
423}
424
425pub fn delete_standardize_call_element(
434 config: &str,
435 params: DeleteStandardizeCallElementParams,
436) -> Result<String> {
437 let mut config_data: Value =
438 serde_json::from_str(config).map_err(|e| SzConfigError::JsonParse(e.to_string()))?;
439
440 let final_felem_id = params.felem_id.unwrap_or(-1);
441
442 let element_exists = config_data["G2_CONFIG"]["CFG_SFCALL"]
444 .as_array()
445 .map(|arr| {
446 arr.iter().any(|item| {
447 item.get("FTYPE_ID").and_then(|v| v.as_i64()) == Some(params.ftype_id)
448 && item.get("SFUNC_ID").and_then(|v| v.as_i64()) == Some(params.sfunc_id)
449 && item.get("FELEM_ID").and_then(|v| v.as_i64()) == Some(final_felem_id)
450 })
451 })
452 .unwrap_or(false);
453
454 if !element_exists {
455 return Err(SzConfigError::NotFound(
456 "Standardize call element not found".to_string(),
457 ));
458 }
459
460 if let Some(sfcall_array) = config_data["G2_CONFIG"]["CFG_SFCALL"].as_array_mut() {
462 sfcall_array.retain(|item| {
463 !(item.get("FTYPE_ID").and_then(|v| v.as_i64()) == Some(params.ftype_id)
464 && item.get("SFUNC_ID").and_then(|v| v.as_i64()) == Some(params.sfunc_id)
465 && item.get("FELEM_ID").and_then(|v| v.as_i64()) == Some(final_felem_id))
466 });
467 }
468
469 serde_json::to_string(&config_data).map_err(|e| SzConfigError::JsonParse(e.to_string()))
470}
471
472pub fn set_standardize_call_element(
481 config: &str,
482 _params: SetStandardizeCallElementParams,
483) -> Result<String> {
484 Ok(config.to_string())
486}