Skip to main content

Module 08: Quality Checks in ODSL

In this module you will write quality check scripts in ODSL, upload them to the platform, and attach them to the dataset you configured in Module 07.

What is a Quality Check Script?​

A quality check script is an ODSL script stored in the script service. It contains functions that the platform calls when evaluating dataset delivery. Each function has access to two global variables:

VariableDescription
#EVENTSAn array of all the events being checked for this delivery
#LOGA log object for recording failure details
#DSIDThe dataset ID being checked
#ONDATEThe delivery date being evaluated
#DATASETThe dataset information object

Each function must return one of three strings:

Return valueMeaning
"valid"All checks passed
"warning"A potential issue was found — data is flagged but not blocked
"failed"A check failed — for critical checks this blocks downstream use

The platform supports two categories of check script:

CategoryDescription
dataset-qualityQuality checks — return "warning" or "valid"
dataset-criticalCritical checks — return "failed" or "valid"

Step 1: Create the Script Files​

Create two script files in your local project folder or VS Code ODSL extension workspace. Scripts uploaded to the server must not be wrapped in //#region blocks — add the test code at the bottom of each file inside a //#region for local debugging instead.

File 1: my_gas_hub_quality_checks.odsl​

/**
* Quality check functions for MY.GAS.HUB settlement price dataset
* Script: my_gas_hub_quality_checks
* @category dataset-quality
*/

// ============================================================
// Quality Check: Validate settlement price is within range
// ============================================================
function checkSettlementPrice()
checkSettlementPrice = "valid"
#LOG.failures = []
print "Checking " + #EVENTS.size() + " events for settlement price range for dataset: " + #DSID + " for " + #ONDATE

if #EVENTS.size() == 0
log warn "No events to check"
checkSettlementPrice = "warning"
return
end

for evt in #EVENTS
price = evt.price

if price == null
checkSettlementPrice = "warning"
#LOG.failures.add("Missing price on event " + evt.id)
elseif price < 0.5
checkSettlementPrice = "warning"
#LOG.failures.add("Price " + price + " below minimum threshold of 0.5 for event " + evt.id)
elseif price > 5
checkSettlementPrice = "warning"
#LOG.failures.add("Price " + price + " exceeds maximum threshold of 5 for event " + evt.id)
end
next
end


// ============================================================
// Quality Check: Detect suspicious day-on-day price change
// ============================================================
function checkPriceMovement()
checkPriceMovement = "valid"
#LOG.failures = []
print "Checking " + #EVENTS.size() + " events for price movement for dataset: " + #DSID + " for " + #ONDATE

if #EVENTS.size() == 0
log warn "No events to check"
checkPriceMovement = "warning"
return
end

for evt in #EVENTS
price = evt.price
prevPrice = evt.prevPrice

if price == null or prevPrice == null
// Cannot check movement without both values — skip
checkPriceMovement = "warning"
#LOG.failures.add("Insufficient data for movement check on event " + evt.id)
elseif prevPrice != 0
change = abs((price - prevPrice) / prevPrice) * 100
if change > 20
checkPriceMovement = "warning"
#LOG.failures.add("Price moved " + formatNumber(change, "0.00") + "% vs previous day for event " + evt.id)
end
end
next
end


//#region Test checkSettlementPrice
use training
#EVENTS = ${event:"MY.GAS.HUB:SETTLEMENTS"}
#DSID = "TRAINING.MYGASHUB.SETTLEMENTS"
#ONDATE = "2025-03-03"
#LOG = Object()

result = checkSettlementPrice()
print "Settlement price check: " + result
if #LOG.failures != null
print #LOG.failures
end
//#endregion

//#region Test checkPriceMovement
use training
#EVENTS = ${event:"MY.GAS.HUB:SETTLEMENTS"}
#DSID = "TRAINING.MYGASHUB.SETTLEMENTS"
#ONDATE = "2025-03-03"
#LOG = Object()

result = checkPriceMovement()
print "Price movement check: " + result
if #LOG.failures != null
print #LOG.failures
end
//#endregion

File 2: my_gas_hub_critical_checks.odsl​

Critical checks must be in a separate file with the dataset-critical category.

/**
* Critical check functions for MY.GAS.HUB settlement price dataset
* Script: my_gas_hub_critical_checks
* @category dataset-critical
*/

// ============================================================
// Critical Check: Confirm events are present for the date
// ============================================================
function criticalPriceCheck()
criticalPriceCheck = "valid"
#LOG.failures = []
print "Checking " + #EVENTS.size() + " events for critical price check for dataset: " + #DSID + " for " + #ONDATE

if #EVENTS.size() == 0
criticalPriceCheck = "failed"
#LOG.failures.add("No settlement events found for " + #ONDATE + " — downstream processes blocked")
return
end

for evt in #EVENTS
if evt.price == null
criticalPriceCheck = "failed"
#LOG.failures.add("Missing price on event " + evt.id + " — downstream processes blocked")
end
next
end


//#region Test criticalPriceCheck
use training
#EVENTS = ${event:"MY.GAS.HUB:SETTLEMENTS"}
#DSID = "TRAINING.MYGASHUB.SETTLEMENTS"
#ONDATE = "2025-03-03"
#LOG = Object()

result = criticalPriceCheck()
print "Critical price check: " + result
if #LOG.failures != null
print #LOG.failures
end
//#endregion

Step 2: Upload the Scripts to the Platform​

Because we are working in the training environment, scripts must be uploaded using an ODSL script rather than the VS Code right-click upload, so that the training environment is correctly targeted.

Create a third file called upload_scripts.odsl and run it using Debug Region:

//#region
use training

s1 = ${script:file/"/src/odsl-demo/Training/my_gas_hub_quality_checks.odsl"}
s1._id = "my_gas_hub_quality_checks"
save s1

s2 = ${script:file/"/src/odsl-demo/Training/my_gas_hub_critical_checks.odsl"}
s2._id = "my_gas_hub_critical_checks"
save s2

//#endregion
File Paths

Update the file paths to match the location of your script files within your project. The _id values set here are what will be used to reference the scripts everywhere else.

Verify the Upload​

//#region
use training
// Confirm both scripts are available
qs = find ${script} where _id = "my_gas_hub_quality_checks"
print qs

cs = find ${script} where _id = "my_gas_hub_critical_checks"
print cs
//#endregion

Step 3: Test the Functions Locally​

The test regions at the bottom of each script file let you debug directly without needing to trigger a full dataset run. In VS Code, right-click anywhere inside a //#region block and select Debug Region to run just that section.

The test code sets up the global variables (#EVENTS, #DSID, #ONDATE, #LOG) to simulate what the platform would pass at runtime, then calls the function and prints the result.

Testing with Bad Data

To test a failing check, temporarily modify a settlement event to have an out-of-range or missing price, then re-run the test region. Confirm the function returns "warning" or "failed" with the expected failure message logged, then restore the correct value.


Step 4: Attach the Scripts to the Dataset​

Option A: Using the Portal​

Once both scripts are uploaded, open the dataset in the portal and attach the checks via the dropdown selectors:

  1. Open the Dataset Monitoring dashboard, hover over TRAINING.MYGASHUB.SETTLEMENTS and select Edit to open the side panel
  2. In the Quality Checks section, add two checks:
    • Script: my_gas_hub_quality_checks / Function: checkSettlementPrice
    • Script: my_gas_hub_quality_checks / Function: checkPriceMovement
  3. In the Critical Checks section, add:
    • Script: my_gas_hub_critical_checks / Function: criticalPriceCheck
  4. Click Save

Option B: Using ODSL Code​

//#region
use training
// Fetch the dataset configuration
ds = ${dataset:"TRAINING.MYGASHUB.SETTLEMENTS"}

// Add quality checks
qualityCheck1 = SimpleObject()
qualityCheck1.type = "function"
qualityCheck1.script = "my_gas_hub_quality_checks"
qualityCheck1.name = "Check settlement price"
qualityCheck1.expression = "checkSettlementPrice()"

qualityCheck2 = SimpleObject()
qualityCheck2.type = "function"
qualityCheck2.script = "my_gas_hub_quality_checks"
qualityCheck2.name = "Check price movement"
qualityCheck2.expression = "checkPriceMovement()"

// Add critical checks
criticalCheck1 = SimpleObject()
criticalCheck1.type = "function"
criticalCheck1.script = "my_gas_hub_critical_checks"
criticalCheck1.name = "Critical price check"
criticalCheck1.expression = "criticalPriceCheck()"

ds.checks = [qualityCheck1, qualityCheck2]
ds.criticalChecks = [criticalCheck1]

// Save the updated dataset
save ${dataset:ds}

print "Quality checks attached to dataset"
//#endregion

Step 5: Trigger and Review Checks in the Portal​

  1. Open the Dataset Monitoring dashboard and select TRAINING.MYGASHUB.SETTLEMENTS
  2. Select a date for which you have settlement data
  3. Use the dataset actions to run the quality checks again
  4. The General tab will show the result of each check, and the Quality Status icon will show the overall result: unchecked, valid, warning, failed or severe

Step 6: Query Dataset Status in a Script​

//#region
use training
// Check if the dataset is complete for today
today = format(Date(), "yyyy-MM-dd")
isComplete = isDatasetComplete("TRAINING.MYGASHUB.SETTLEMENTS", today)

if isComplete
print "Dataset is complete for " + today
else
// Get detailed delivery info
delivery = getDatasetDelivery("TRAINING.MYGASHUB.SETTLEMENTS", today)
print "Dataset not complete. Details:"
print delivery
end
//#endregion

Summary​

You have now completed the full training path:

ModuleWhat You Did
01Understood the core platform concepts
02Created and updated events using ODSL
03Created and updated events using Excel
04Built EventTimeSeries from event data
05Created SmartTimeSeries for currency and unit conversion
06Built forward curves from events and Smart Curve expressions
07Configured dataset monitoring in the portal
08Wrote quality check functions and attached them to the dataset

Next Steps​

In Module 09 you will raise alerts for late or missing deliveries and quality check violations, and be notified when they happen.

Getting Help

You can ask the Fusion AI assistant in the portal for help writing ODSL scripts, explaining platform concepts, or diagnosing quality check failures.