Skip to content

Express indicators requirements using DSL rules #98

@ndrhzn

Description

@ndrhzn

Context & Motivation

Currently, field requirements for usability indicators and red flags are defined as a mix of code logic (e.g. when we choose which set of fields to use as a proxy for buyer or award value), and a dictionary with a set of required fields for each indicator. See component_setup_usability for a reference.

This might be hard to maintain and follow, as conditions for choosing proxy fields are separated from indicator definitions.

What we can do instead is define requirements for indicators using DSL rules.

Proposed Solution

For each indicator (and red flag), define a rule using nested structure where:

  • {"all": [ ... ]} means all sub-requirements are mandatory (logical AND)
  • {"any": [ ... ]} means at least one sub-requirement is needed (logical OR)

Combine rules into one and rewrite the 'usability checks' function to take that dictionary as an input.

Example

U066 'Percent of contracts that exceed budget' can be calculated using either planning or tender values.

Currently it is expressed in two parts

Selection of a proxy fields for 'budget':

 # U066, U067
    if "planning/budget/amount/amount" in fields_list and "planning/budget/amount/currency":
        planning = ["planning/budget/amount/amount", "planning/budget/amount/currency"]
    elif "tender/value/amount" in fields_list and "tender/value/currency":
        planning = ["tender/value/amount", "tender/value/currency"]
    else:
        planning = ["planning/budget/amount/amount", "planning/budget/amount/currency"]

Construction of an indicator requirements:

{
  "Percent of contracts that exceed budget": [
    [
      "U066"
    ],
    [
      "ocid",
      "contracts/status",
      "contracts/value/amount",
      "contracts/value/currency",
      "*planning"
    ]
  ]
}

Alternatively it can be expressed as a rule:

U066_REQUIREMENT = {
  "all": [
    "ocid",
    "contracts/status",
    "contracts/value/amount",
    "contracts/value/currency",
    {"any": [
      {"all": ["planning/budget/amount/amount", "planning/budget/amount/currency"]},
      {"all": ["tender/value/amount", "tender/value/currency"]}
    ]}
  ]
}

Benefits

Defined this way, rules should be more readable and maintainable. It should be easy to add new requirements and conditions if needed.

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions