Change Order Validations
Overview
Change Order Validations provide a comprehensive system for ensuring data integrity and enforcing business rules throughout your change management process. This powerful feature allows you to run both built-in system validations and custom validation rules that align with your organization's specific requirements.
Why Validations Matter
In complex engineering environments, a single oversight can lead to costly errors, production delays, or compliance issues. The validation system helps you:
- Prevent Errors Early: Catch issues before changes are approved and implemented 
- Enforce Standards: Ensure all changes meet your organization's requirements 
- Maintain Consistency: Apply the same rules across all change orders 
- Provide Transparency: Give reviewers clear visibility into validation results 
- Enable Custom Logic: Create organization-specific validation rules 
Understanding Validation Types
The Duro platform provides two types of validations:
System Validations
Built-in validations that run automatically to ensure fundamental data integrity:
- Items must not exist in other OPEN change orders (prevents conflicts) 
- Required fields must be populated 
- Data types must match expected formats 
- Cross-references must be valid 
Custom Validations
JavaScript-based rules you create to enforce your specific business logic:
- Cost threshold checks 
- Part number format validation 
- Required approver verification 
- Impact assessment requirements 
- Custom field dependencies 
Running Validations
Validations can be triggered manually at any time during the DRAFT state of the change order lifecycle. Here's how to run validations and interpret the results:
Basic Validation Query
mutation ValidateChangeOrder($changeOrderId: ID!) {
  changeOrders {
    validate(id: $changeOrderId) {
      id
      isValid  # Overall validation result
      validationRun {
        id
        state  # PASS or FAIL
        summary {
          passCount
          failCount
          warningCount
        }
        results(pagination: { first: 50 }) {
          edges {
            node {
              name
              state
              errorMessage
            }
          }
        }
      }
    }
  }
}Example Response
{
  "data": {
    "changeOrders": {
      "validate": {
        "id": "123e4567-e89b-12d3-a456-426614174000",
        "isValid": false,
        "validationRun": {
          "id": "987fcdeb-51a2-43d1-9876-543210fedcba",
          "state": "FAIL",
          "summary": {
            "passCount": 8,
            "failCount": 2,
            "warningCount": 1
          },
          "results": {
            "edges": [
              {
                "node": {
                  "name": "Items must not exist in other OPEN Change Orders",
                  "state": "FAIL",
                  "errorMessage": "Item P123-456 exists in Change Order CO-2024-001"
                }
              }
            ]
          }
        }
      }
    }
  }
}Accessing Validation History
Every validation run is stored, allowing you to track how validation results change over time as issues are resolved.
Viewing Latest Validation Results
query GetLatestValidation($changeOrderId: ID!) {
  changeOrders {
    get(filter: { ids: [$changeOrderId] }) {
      connection {
        edges {
          node {
            id
            name
            isValid
            latestValidationRun {
              id
              state
              createdAt
              createdBy {
                name
              }
              summary {
                passCount
                failCount
                warningCount
              }
              # Get detailed results with logs
              results(pagination: { first: 100 }) {
                edges {
                  node {
                    name
                    validationType  # SYSTEM or CUSTOM
                    state          # PASS, FAIL, or WARNING
                    onFailure      # ERROR or WARNING
                    errorMessage
                    # Access validation logs for debugging
                    logs {
                      error {
                        message
                      }
                      info {
                        message
                      }
                      all {
                        message
                        type
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}Viewing Historical Validation Runs
Track how validation results have changed over time:
query GetValidationHistory($changeOrderId: ID!) {
  changeOrders {
    get(filter: { ids: [$changeOrderId] }) {
      connection {
        edges {
          node {
            id
            # Get all historical validation runs
            validationRuns(pagination: { first: 10 }) {
              edges {
                node {
                  id
                  collectionId
                  state
                  createdAt
                  createdBy {
                    name
                  }
                  summary {
                    passCount
                    failCount
                    warningCount
                  }
                  # Can drill into specific failed validations
                  results(pagination: { first: 100 }) {
                    edges {
                      node {
                        name
                        state
                        errorMessage
                      }
                    }
                  }
                }
              }
              totalCount
            }
          }
        }
      }
    }
  }
}Understanding Validation Results
Each validation result provides detailed information to help you understand and resolve issues:
Validation States
- PASS: The validation succeeded without issues 
- FAIL: The validation failed and must be resolved 
- WARNING: The validation found potential issues that should be reviewed 
OnFailure Behavior
- ERROR: Blocks the change order from proceeding (hard stop) 
- WARNING: Alerts reviewers but doesn't block progress (soft warning) 
Validation Logs
Each validation generates detailed logs that help with debugging:
logs {
  # Informational messages about validation execution
  info {
    message
  }
  # Warnings about potential issues
  warn {
    message
  }
  # Error details when validation fails
  error {
    message
  }
  # All logs in chronological order
  all {
    message
    type  # "info", "warn", "error", or "log"
  }
}Working with Custom Validations
Custom validations allow you to implement organization-specific business rules. When a custom validation runs, you can access both the validation result and the underlying rule definition:
query GetCustomValidationDetails($changeOrderId: ID!) {
  changeOrders {
    get(filter: { ids: [$changeOrderId] }) {
      connection {
        edges {
          node {
            latestValidationRun {
              results(pagination: { first: 50 }) {
                edges {
                  node {
                    name
                    validationType
                    state
                    errorMessage
                    # Only populated for CUSTOM validations
                    validationRule {
                      id
                      name
                      type
                      version
                      code  # The JavaScript validation code
                      library {
                        id
                        name
                      }
                    }
                    # Debug custom validation execution
                    logs {
                      all {
                        message
                        type
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}Practical Examples
Example 1: Check Only Failed Validations
When debugging validation failures, focus on just the problems:
query GetFailedValidations($changeOrderId: ID!) {
  changeOrders {
    get(filter: { ids: [$changeOrderId] }) {
      connection {
        edges {
          node {
            id
            name
            isValid
            latestValidationRun {
              state
              summary {
                failCount
                warningCount
              }
              # Fetch all results, then filter client-side
              results(pagination: { first: 100 }) {
                edges {
                  node {
                    name
                    state
                    errorMessage
                    logs {
                      error {
                        message
                      }
                    }
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}Then filter the results in your application code:
const failedValidations = data.changeOrders.get.connection.edges[0]
  .node.latestValidationRun.results.edges
  .filter(edge => edge.node.state === 'FAIL' || edge.node.state === 'WARNING');Example 2: Monitor Validation Progress
Track validation improvements over multiple runs:
query CompareValidationRuns($changeOrderId: ID!) {
  changeOrders {
    get(filter: { ids: [$changeOrderId] }) {
      connection {
        edges {
          node {
            # Current state
            latestValidationRun {
              createdAt
              summary {
                passCount
                failCount
                warningCount
              }
            }
            # Historical comparison
            validationRuns(pagination: { first: 5 }) {
              edges {
                node {
                  createdAt
                  summary {
                    passCount
                    failCount
                    warningCount
                  }
                }
              }
            }
          }
        }
      }
    }
  }
}Example 3: Validation Integration Workflow
Here's a complete workflow for integrating validations into your change order process:
// 1. Create or update a change order
const changeOrderId = await createChangeOrder(changeOrderData);
// 2. Run validations
const validationResult = await runValidation(changeOrderId);
// 3. Check if valid
if (!validationResult.isValid) {
  // 4. Get detailed failure information
  const failures = validationResult.validationRun.results.edges
    .filter(edge => edge.node.state !== 'PASS')
    .map(edge => ({
      name: edge.node.name,
      error: edge.node.errorMessage,
      severity: edge.node.onFailure
    }));
  // 5. Display failures to user
  displayValidationErrors(failures);
  // 6. Allow user to fix issues
  await promptUserToResolveIssues(failures);
  // 7. Re-run validations after fixes
  const retryResult = await runValidation(changeOrderId);
  if (retryResult.isValid) {
    console.log('All validations passed!');
  }
}
// 8. Proceed with approval workflow only if valid
if (validationResult.isValid) {
  await submitForApproval(changeOrderId);
}Best Practices
1. Run Validations Early and Often
Don't wait until the approval stage to run validations. Run them:
- After initial change order creation 
- After any significant updates 
- Before submitting for approval 
- After resolving validation failures 
2. Provide Clear Error Messages
When creating custom validations, ensure error messages are actionable:
- ✅ Good: "Part number ABC-123 must have an associated drawing document" 
- ❌ Avoid: "Validation failed" 
3. Use Warnings Appropriately
Reserve warnings for issues that should be reviewed but don't necessarily block progress:
- Missing optional documentation 
- Unusual but acceptable values 
- Recommendations for best practices 
4. Monitor Validation Trends
Track validation patterns across change orders to identify:
- Common failure points in your process 
- Training opportunities for users 
- Potential system improvements 
5. Leverage Validation Logs
Use the detailed logs to:
- Debug custom validation logic 
- Understand validation execution flow 
- Provide context to users about failures 
Troubleshooting
Common Issues
Validation Runs But Shows No Results
Ensure you're requesting the results field with proper pagination:
validationRun {
  results(pagination: { first: 100 }) {  # Don't forget pagination
    edges {
      node {
        name
        state
      }
    }
  }
}Custom Validation Not Running
Verify that:
- The validation rule is active in your library 
- The validation rule code is syntactically correct 
- The change order meets the criteria for the validation to run 
Inconsistent Validation Results
Check for:
- Data changes between validation runs 
- Updates to validation rules 
- Different validation contexts (some validations may be conditional) 
Next Steps
- Review your organization's validation requirements 
- Implement custom validations for your specific needs 
- Integrate validation checks into your change order workflow 
- Monitor validation metrics to improve your process 
For more information on creating custom validation rules, see the Change Order Workflows documentation.
Last updated
Was this helpful?
