tricc-oo 1.6.5__tar.gz → 1.6.5.dev1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (57) hide show
  1. {tricc_oo-1.6.5/tricc_oo.egg-info → tricc_oo-1.6.5.dev1}/PKG-INFO +1 -1
  2. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/pyproject.toml +1 -1
  3. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/tricc_to_xls_form.py +8 -2
  4. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/base.py +1 -1
  5. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/serializers/xls_form.py +33 -17
  6. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/dhis2_form.py +27 -76
  7. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/xls_form.py +1 -4
  8. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/xlsform_cht.py +0 -3
  9. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1/tricc_oo.egg-info}/PKG-INFO +1 -1
  10. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo.egg-info/top_level.txt +1 -0
  11. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/LICENSE +0 -0
  12. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/README.md +0 -0
  13. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/setup.cfg +0 -0
  14. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tests/build.py +0 -0
  15. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tests/test_build.py +0 -0
  16. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tests/test_cql.py +0 -0
  17. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tests/to_ocl.py +0 -0
  18. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/__init__.py +0 -0
  19. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/__init__.py +0 -0
  20. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/codesystem_to_ocl.py +0 -0
  21. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/cql/cqlLexer.py +0 -0
  22. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/cql/cqlListener.py +0 -0
  23. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/cql/cqlParser.py +0 -0
  24. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/cql/cqlVisitor.py +0 -0
  25. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/cql_to_operation.py +0 -0
  26. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/datadictionnary.py +0 -0
  27. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/drawio_type_map.py +0 -0
  28. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/utils.py +0 -0
  29. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/converters/xml_to_tricc.py +0 -0
  30. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/__init__.py +0 -0
  31. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/calculate.py +0 -0
  32. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/lang.py +0 -0
  33. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/ocl.py +0 -0
  34. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/ordered_set.py +0 -0
  35. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/models/tricc.py +0 -0
  36. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/parsers/__init__.py +0 -0
  37. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/parsers/xml.py +0 -0
  38. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/serializers/__init__.py +0 -0
  39. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/serializers/planuml.py +0 -0
  40. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/__init__.py +0 -0
  41. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/input/__init__.py +0 -0
  42. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/input/base_input_strategy.py +0 -0
  43. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/input/drawio.py +0 -0
  44. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/base_output_strategy.py +0 -0
  45. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/fhir_form.py +0 -0
  46. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/html_form.py +0 -0
  47. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/openmrs_form.py +0 -0
  48. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/spice.py +0 -0
  49. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/xlsform_cdss.py +0 -0
  50. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/strategies/output/xlsform_cht_hf.py +0 -0
  51. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/visitors/__init__.py +0 -0
  52. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/visitors/tricc.py +0 -0
  53. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/visitors/utils.py +0 -0
  54. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo/visitors/xform_pd.py +0 -0
  55. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo.egg-info/SOURCES.txt +0 -0
  56. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo.egg-info/dependency_links.txt +0 -0
  57. {tricc_oo-1.6.5 → tricc_oo-1.6.5.dev1}/tricc_oo.egg-info/requires.txt +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.5
3
+ Version: 1.6.5.dev1
4
4
  Summary: Python library that converts CDSS L2 in L3
5
5
  Project-URL: Homepage, https://github.com/SwissTPH/tricc
6
6
  Project-URL: Issues, https://github.com/SwissTPH/tricc/issues
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "tricc-oo"
7
- version = "1.6.5"
7
+ version = "1.6.5.dev001"
8
8
  description = "Python library that converts CDSS L2 in L3"
9
9
  readme = "README.md"
10
10
  requires-python = ">=3.8"
@@ -1,6 +1,6 @@
1
1
  import logging
2
2
  from tricc_oo.converters.utils import clean_name, clean_str
3
- from tricc_oo.models.tricc import TriccNodeSelectOption, TRICC_TRUE_VALUE, TRICC_FALSE_VALUE
3
+ from tricc_oo.models.tricc import TriccNodeSelectOption, TRICC_TRUE_VALUE, TRICC_FALSE_VALUE, TriccNodeActivity
4
4
  from tricc_oo.models.calculate import TriccNodeInput
5
5
  from tricc_oo.models.base import TriccNodeBaseModel, TriccStatic, TriccReference
6
6
 
@@ -64,8 +64,14 @@ def get_export_name(node, replace_dots=True):
64
64
  return node
65
65
  else:
66
66
  node.gen_name()
67
- if isinstance(node, TriccNodeSelectOption):
67
+ if isinstance(node, TriccNodeActivity) and getattr(node, 'instance', 1)>1:
68
+ node.export_name = clean_name(
69
+ node.name + INSTANCE_SEPARATOR + str(node.instance),
70
+ replace_dots=replace_dots,
71
+ )
72
+ elif isinstance(node, TriccNodeSelectOption):
68
73
  node.export_name = node.name
74
+
69
75
  elif node.last is False:
70
76
  node.export_name = clean_name(
71
77
  node.name + VERSION_SEPARATOR + str(node.version),
@@ -11,7 +11,7 @@ from tricc_oo.models.ordered_set import OrderedSet
11
11
 
12
12
  logger = logging.getLogger("default")
13
13
 
14
- Expression = Annotated[str, StringConstraints(pattern=r".+")]
14
+ Expression = Annotated[str, StringConstraints(pattern=r"^[^\\/\:]+$")]
15
15
 
16
16
  triccId = Annotated[str, StringConstraints(pattern=r"^[^\\/\: ]+$")]
17
17
 
@@ -6,13 +6,14 @@ from tricc_oo.converters.tricc_to_xls_form import (
6
6
  get_export_name, BOOLEAN_MAP
7
7
  )
8
8
  from tricc_oo.models.lang import SingletonLangClass
9
- from tricc_oo.converters.utils import clean_name, remove_html
9
+ from tricc_oo.converters.utils import clean_name, remove_html, generate_id
10
10
  from tricc_oo.models.base import (
11
11
  TriccOperator,
12
12
  TriccOperation, TriccStatic, TriccReference, and_join, TriccNodeType
13
13
  )
14
14
  from tricc_oo.models.calculate import (
15
15
  TriccNodeDisplayCalculateBase,
16
+ TriccNodeCalculate
16
17
  )
17
18
  from tricc_oo.models.tricc import (
18
19
  TriccNodeActivity, TriccNodeBaseModel, TriccNodeSelectMultiple, TriccNodeSelectOption,
@@ -38,6 +39,7 @@ logger = logging.getLogger("default")
38
39
  langs = SingletonLangClass()
39
40
  TRICC_CALC_EXPRESSION = "${{{0}}}>0"
40
41
 
42
+ def get_export_group_name(in_node):return f"gcalc_{get_export_name(in_node)}"
41
43
 
42
44
  def start_group(
43
45
  strategy,
@@ -60,24 +62,38 @@ def start_group(
60
62
  groups[name] = 0
61
63
  is_activity = isinstance(cur_group, TriccNodeActivity)
62
64
  relevance = relevance and cur_group.relevance is not None and cur_group.relevance != ""
63
-
64
- group_calc_required = False and relevance and not is_activity and len(relevance) > 100
65
-
65
+ past_instances = len(getattr(cur_group.base_instance, "instances", []))
66
+ group_calc_required = relevance is not None and (len(str(relevance)) > 100 or past_instances>1)
67
+ calc = None
68
+ if group_calc_required and getattr(cur_group.relevance, 'operator', None) != TriccOperator.ISTRUE:
69
+
70
+ calc = TriccNodeCalculate(
71
+ id=generate_id(get_export_group_name(name)),
72
+ group=cur_group,
73
+ activity=cur_group.activity,
74
+ name=get_export_group_name(name),
75
+ expression=cur_group.relevance
76
+ )
77
+ if calc not in cur_group.calculates:
78
+ cur_group.calculates.append(calc)
79
+ processed_nodes.add(calc)
80
+
81
+ cur_group.relevance = TriccOperation(
82
+ TriccOperator.ISTRUE,
83
+ [calc]
84
+ )
85
+
66
86
  relevance_expression = cur_group.relevance
67
87
  relevance_expression = get_applicability_expression(cur_group, processed_nodes, process, relevance_expression)
68
88
  relevance_expression = get_prev_instance_skip_expression(cur_group, processed_nodes, process, relevance_expression)
69
89
  relevance_expression = get_process_skip_expression(cur_group, processed_nodes, process, relevance_expression)
70
90
 
91
+
71
92
  if not relevance:
72
- relevance_expression = ""
93
+ relevance_expression_str = ""
73
94
  elif isinstance(relevance_expression, (TriccOperation, TriccStatic)):
74
- relevance_expression = strategy.get_tricc_operation_expression(relevance_expression)
75
-
76
- # elif is_activity:
77
- # relevance_expression = TRICC_CALC_EXPRESSION.format(get_export_name(cur_group.root))
78
- elif group_calc_required:
79
- relevance_expression = TRICC_CALC_EXPRESSION.format("gcalc_" + name)
80
-
95
+ relevance_expression_str = strategy.get_tricc_operation_expression(relevance_expression)
96
+
81
97
  # group
82
98
  values = []
83
99
  for column in SURVEY_MAP:
@@ -91,23 +107,23 @@ def start_group(
91
107
  if relevance_expression is True:
92
108
  values.append("")
93
109
  else:
94
- values.append(relevance_expression)
110
+ values.append(relevance_expression_str)
95
111
 
96
112
  else:
97
113
  values.append(get_xfrom_trad(strategy, cur_group, column, SURVEY_MAP))
98
114
  df_survey.loc[len(df_survey)] = values
99
115
 
100
116
  # calc
101
- if group_calc_required and len(df_calculate[df_calculate["name"] == "gcalc_" + name]) == 0:
117
+ if calc and len(df_calculate[df_calculate["name"] == get_export_group_name(name)]) == 0:
102
118
  calc_values = []
103
119
  for column in SURVEY_MAP:
104
120
  if column == "type":
105
121
  calc_values.append("calculate")
106
122
  elif column == "name":
107
- value = "gcalc_" + name
123
+ value = get_export_name(calc)
108
124
  calc_values.append(value)
109
125
  elif column == "calculation":
110
- calc_values.append(get_attr_if_exists(strategy, cur_group, "relevance", SURVEY_MAP))
126
+ calc_values.append(strategy.get_tricc_operation_expression(calc.expression))
111
127
  elif column == "relevance":
112
128
  calc_values.append("")
113
129
  else:
@@ -399,7 +415,7 @@ def get_more_info_select(strategy, node):
399
415
  if column == "type":
400
416
  values.append("select_one more_info")
401
417
  elif column == "label":
402
- values.append(strategy.get_empty_label())
418
+ values.append("NO_LABEL")
403
419
  elif column == "name":
404
420
  values.append(get_export_name(node) + "_optin")
405
421
  elif column == "hint":
@@ -25,8 +25,6 @@ from tricc_oo.models.tricc import (
25
25
  TriccNodeDisplayModel,
26
26
  TriccNodeCalculateBase,
27
27
  TriccNodeActivity,
28
- TriccNodeSelect,
29
- TriccNodeSelectYesNo,
30
28
  )
31
29
  from tricc_oo.models.calculate import TriccNodeDisplayCalculateBase
32
30
  from tricc_oo.models.ordered_set import OrderedSet
@@ -68,22 +66,18 @@ class DHIS2Strategy(BaseOutPutStrategy):
68
66
 
69
67
  def get_export_name(self, r):
70
68
  if isinstance(r, TriccNodeSelectOption):
71
- ret = self.get_option_value(r.name)
69
+ return self.get_option_value(r.name)
72
70
  elif isinstance(r, str):
73
- ret = self.get_option_value(r)
71
+ return self.get_option_value(r)
74
72
  elif isinstance(r, TriccStatic):
75
73
  if isinstance(r.value, str):
76
- ret = self.get_option_value(r.value)
74
+ return self.get_option_value(r.value)
77
75
  elif isinstance(r.value, bool):
78
- ret = str(r.value).lower()
76
+ return str(r.value).lower()
79
77
  else:
80
- ret = r.value
81
- else:
82
- ret = get_export_name(r)
83
- if isinstance(ret, str):
84
- return ret[:50]
78
+ return r.value
85
79
  else:
86
- return ret
80
+ return get_export_name(r)
87
81
 
88
82
  def generate_id(self, name):
89
83
  """Generate DHIS2-compliant UID: 1 letter + 10 alphanumeric characters"""
@@ -145,15 +139,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
145
139
  raise NotImplementedError(
146
140
  f"This type of operation '{operation.operator}' is not supported in this strategy"
147
141
  )
148
- def get_display(self, node):
149
- if hasattr(node, 'label') and node.label:
150
- ret = node.label
151
- elif hasattr(node, 'name') and node.name:
152
- ret = node.name
153
- else:
154
- ret = str(node.id)
155
- return ret.replace('\u00a0', ' ').strip()
156
-
142
+
157
143
  def execute(self):
158
144
  version = datetime.datetime.now().strftime("%Y%m%d%H%M")
159
145
  logger.info(f"build version: {version}")
@@ -237,13 +223,11 @@ class DHIS2Strategy(BaseOutPutStrategy):
237
223
  self.program_rule_actions.append(program_rule_action)
238
224
 
239
225
  # Create program rule referencing the action
240
- condition = self.simplify_expression(f"!({relevance_str})") # Negate for hide when true
241
- condition = self.simplify_expression(condition)
242
226
  self.program_rules.append({
243
227
  "id": rule_id,
244
- "name": f"Hide `{self.get_export_name(node)}` when condition met",
245
- "description": f"Hide `{self.get_display(node)}` based on relevance",
246
- "condition": condition,
228
+ "name": f"Hide {node.get_name()} when condition met",
229
+ "description": f"Hide {node.get_name()} based on relevance",
230
+ "condition": f"!({relevance_str})", # Negate for hide when true
247
231
  "programRuleActions": [{"id": action_id}]
248
232
  })
249
233
  return True
@@ -273,15 +257,11 @@ class DHIS2Strategy(BaseOutPutStrategy):
273
257
  "id": de_id,
274
258
  "name": self.get_export_name(node),
275
259
  "shortName": node.name[:50],
276
- "displayFormName":self.get_display(node),
277
- "formName": self.get_display(node),
260
+ "displayFormName": getattr(node, 'label', node.name).replace('\u00a0', ' ').strip(),
278
261
  "valueType": value_type,
279
262
  "domainType": "TRACKER",
280
263
  "aggregationType": "NONE"
281
264
  }
282
-
283
- if issubclass(node.__class__, TriccNodeSelect) and not isinstance(node, TriccNodeSelectYesNo):
284
- data_element["optionSetValue"] = True
285
265
 
286
266
  # Only create optionSet for non-boolean select questions
287
267
  if node.tricc_type in ['select_one', 'select_multiple'] and not is_boolean_question:
@@ -293,7 +273,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
293
273
  # Create the actual optionSet definition
294
274
  option_set = {
295
275
  "id": option_set_id,
296
- "name": f"{self.get_export_name(node)} Options",
276
+ "name": f"{node.name} Options",
297
277
  "shortName": f"{node.name}_opts"[:50],
298
278
  "valueType": "TEXT",
299
279
  "options": []
@@ -308,10 +288,10 @@ class DHIS2Strategy(BaseOutPutStrategy):
308
288
  option_name = option_name.replace('\u00a0', ' ').strip()
309
289
  elif isinstance(option_name, TriccStatic):
310
290
  option_name = str(option_name.value)
311
- # Create separate option entityif
291
+ # Create separate option entity
312
292
  option_def = {
313
293
  "id": option_id,
314
- "name": self.get_display(option),
294
+ "name": option_name,
315
295
  "shortName": option.name[:50],
316
296
  "code": str(self.get_export_name(option))
317
297
  }
@@ -323,20 +303,6 @@ class DHIS2Strategy(BaseOutPutStrategy):
323
303
  self.option_sets[option_set_id] = option_set
324
304
 
325
305
  self.data_elements[node.name] = data_element
326
-
327
- # Create program rule variable for this data element
328
- var_id = self.generate_id(f"var_{node.name}")
329
- var_name = self.get_export_name(node)
330
- program_rule_variable = {
331
- "id": var_id,
332
- "name": var_name,
333
- "programRuleVariableSourceType": "DATAELEMENT_CURRENT_EVENT",
334
- "dataElement": {"id": de_id},
335
- "program": {"id": self.program_metadata["id"]}
336
- }
337
- self.program_rule_variables.append(program_rule_variable)
338
- self.concept_map[node.name] = var_name # Store variable name for #{var_name} references
339
-
340
306
  return data_element
341
307
  return None
342
308
 
@@ -359,10 +325,9 @@ class DHIS2Strategy(BaseOutPutStrategy):
359
325
  mock_node = MockNode(operation_datatype)
360
326
  data_type = self.map_tricc_type_to_dhis2_value_type(mock_node)
361
327
 
362
- var_name = self.get_export_name(node)
363
328
  program_rule_variable = {
364
329
  "id": var_id,
365
- "name": var_name,
330
+ "name": self.get_export_name(node.name)[:50],
366
331
  "programRuleVariableSourceType": "CALCULATED_VALUE",
367
332
  "calculatedValueScript": expression_str,
368
333
  "dataType": data_type,
@@ -371,7 +336,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
371
336
  }
372
337
  self.program_rule_variables.append(program_rule_variable)
373
338
  # Add to concept map for potential referencing
374
- self.concept_map[node.name] = var_name # Store variable name
339
+ self.concept_map[node.name] = var_id
375
340
  return True
376
341
  return False
377
342
 
@@ -709,7 +674,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
709
674
  if isinstance(r, TriccOperation):
710
675
  return self.get_tricc_operation_expression(r)
711
676
  elif isinstance(r, TriccReference):
712
- # Use variable name from concept_map
677
+ # Use DHIS2 ID from concept_map instead of name
713
678
  node_id = self.concept_map.get(r.value.name, self.get_export_name(r.value))
714
679
  return f"#{{{node_id}}}"
715
680
  elif isinstance(r, TriccStatic):
@@ -731,39 +696,25 @@ class DHIS2Strategy(BaseOutPutStrategy):
731
696
  return option
732
697
  return f"'{option}'"
733
698
  elif issubclass(r.__class__, TriccNodeDisplayCalculateBase):
734
- # Use variable name from concept_map
735
- node_id = self.get_export_name(r)
736
- return f"#{{{node_id}}}"
737
- elif issubclass(r.__class__, TriccNodeCalculateBase):
738
- # Use variable name from concept_map
739
- node_id = self.get_export_name(r)
740
- return f"#{{{node_id}}}"
699
+ # Use DHIS2 ID from concept_map instead of name
700
+ node_id = self.concept_map.get(r.name, self.get_export_name(r))
701
+ return f"#{node_id}"
741
702
  elif issubclass(r.__class__, TriccNodeInputModel):
742
- # Use variable name from concept_map
743
- node_id = self.get_export_name(r)
703
+ # Use DHIS2 ID from concept_map instead of name
704
+ node_id = self.concept_map.get(r.name, self.get_export_name(r))
744
705
  return f"#{{{node_id}}}"
745
706
  elif issubclass(r.__class__, TriccNodeBaseModel):
746
- # Use variable name from concept_map
747
- node_id = self.get_export_name(r)
707
+ # Use DHIS2 ID from concept_map instead of name
708
+ node_id = self.concept_map.get(r.name, self.get_export_name(r))
748
709
  return f"#{{{node_id}}}"
749
710
  else:
750
711
  raise NotImplementedError(f"This type of node {r.__class__.__name__} is not supported within an operation")
751
712
 
752
- def simplify_expression(self, expr):
753
- while expr.startswith('!(!(') and expr.endswith('))'):
754
- expr = expr[4:-2]
755
- return expr
756
-
757
713
  def convert_expression_to_string(self, expression):
758
714
  if isinstance(expression, TriccOperation):
759
- expr = self.get_tricc_operation_expression(expression)
715
+ return self.get_tricc_operation_expression(expression)
760
716
  else:
761
- expr = self.get_tricc_operation_operand(expression)
762
-
763
- # Simplify double negations
764
- expr = self.simplify_expression(expr)
765
-
766
- return expr
717
+ return self.get_tricc_operation_operand(expression)
767
718
 
768
719
  # Operation methods for DHIS2 expressions
769
720
  def tricc_operation_equal(self, ref_expressions):
@@ -814,7 +765,7 @@ class DHIS2Strategy(BaseOutPutStrategy):
814
765
 
815
766
  def tricc_operation_selected(self, ref_expressions):
816
767
  # For DHIS2, check if value is selected in multi-select
817
- return f"d2:countIfValue({ref_expressions[0]}, {ref_expressions[1]})>0"
768
+ return f"d2:hasValue({ref_expressions[0]}) && d2:contains({ref_expressions[0]}, {ref_expressions[1]})"
818
769
 
819
770
  def tricc_operation_count(self, ref_expressions):
820
771
  return f"d2:count({ref_expressions[0]})"
@@ -589,14 +589,11 @@ class XLSFormStrategy(BaseOutPutStrategy):
589
589
  exp += ")"
590
590
  return exp
591
591
 
592
- def get_empty_label(self):
593
- return "."
594
-
595
592
  def tricc_operation_if(self, ref_expressions):
596
593
  return f"if({ref_expressions[0]},{ref_expressions[1]},{ref_expressions[2]})"
597
594
 
598
595
  def tricc_operation_contains(self, ref_expressions):
599
- return f"contains({self.clean_coalesce(ref_expressions[0])}, {self.clean_coalesce(ref_expressions[1])})"
596
+ return f"contains('{self.clean_coalesce(ref_expressions[0])}', '{self.clean_coalesce(ref_expressions[1])}')"
600
597
 
601
598
  def tricc_operation_exists(self, ref_expressions):
602
599
  parts = []
@@ -33,9 +33,6 @@ class XLSFormCHTStrategy(XLSFormCDSSStrategy):
33
33
 
34
34
  self.inject_version()
35
35
 
36
- def get_empty_label(self):
37
- return "NO_LABEL"
38
-
39
36
  def get_cht_input(self, start_pages, **kwargs):
40
37
  empty = langs.get_trads("", force_dict=True)
41
38
  df_input = pd.DataFrame(columns=SURVEY_MAP.keys())
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tricc-oo
3
- Version: 1.6.5
3
+ Version: 1.6.5.dev1
4
4
  Summary: Python library that converts CDSS L2 in L3
5
5
  Project-URL: Homepage, https://github.com/SwissTPH/tricc
6
6
  Project-URL: Issues, https://github.com/SwissTPH/tricc/issues
@@ -2,6 +2,7 @@ build
2
2
  diagrams
3
3
  dist
4
4
  locales
5
+ test_output
5
6
  tests
6
7
  tricc_oo
7
8
  uploads
File without changes
File without changes
File without changes
File without changes
File without changes