# Change Order Workflows

## Overview

Change Order Workflow Templates provide a powerful way to customize the approval process for change orders in your PLM library. Using YAML configuration files, you can define multi-stage review processes, specify required approvers, and configure automated actions that align with your organization's change management procedures.

## Why Use Workflow Templates?

Every organization has unique requirements for managing engineering changes. Workflow templates allow you to:

* **Standardize Processes**: Ensure consistent review procedures across all change orders
* **Enforce Compliance**: Meet regulatory requirements with mandatory approval stages
* **Automate Actions**: Configure automatic notifications and resolution behaviors
* **Customize Fields**: Capture the specific information your team needs for decision-making

## Getting Started

Each Duro library comes with two default workflow templates:

1. **Default Template** ([`default.yaml`](https://phoenix-production.durohub.com/static/schemes/change-orders/default.yaml)): A simple single-stage approval workflow
2. **Double Template** ([`double.yaml`](https://phoenix-production.durohub.com/static/schemes/change-orders/double.yaml)): A two-stage workflow with impact analysis fields

These templates serve as starting points that you can customize for your specific needs.

### Basic Workflow Structure

Every workflow template follows this structure:

```yaml
version: '1.0'
description: A clear description of this workflow's purpose
schema_type: change_order_scheme

details:
  info:
    groups:
      # Custom fields for change order creation

stages:
  open:
    # Review stages configuration
  resolved:
    # Actions when change order is resolved
  closed:
    # Final state configuration
```

## Creating Custom Fields

The `details.info.groups` section lets you define custom fields that users fill out when creating a change order. Fields are organized into logical groups for better user experience.

### Example: Adding Change Classification

```yaml
details:
  info:
    groups:
      - name: Change Classification
        icon: mdi-tag-multiple
        fields:
          - name: change_category
            type: enum
            label: Category
            description: Primary category of this change
            options:
              - label: Design Update
                value: design
              - label: Cost Reduction
                value: cost
              - label: Quality Improvement
                value: quality
            validations:
              required: true
```

### Supported Field Types

* **text**: Single-line text input
* **longtext**: Multi-line text area
* **number**: Numeric values
* **date**: Date picker
* **currency**: Monetary values with currency formatting
* **enum**: Single selection from predefined options
* **list**: Multiple selections from predefined options

## Configuring Approval Stages

The `stages.open` section defines your review process. You can create multiple stages that execute sequentially.

### Single-Stage Approval

```yaml
stages:
  open:
    - name: Engineering Review
      types: ['Unanimous', 'Majority', 'Minimum']
      default: Majority
      minReviewers: 2
```

### Multi-Stage Approval

```yaml
stages:
  open:
    - name: Technical Review
      types: ['Unanimous']
      default: Unanimous
      minReviewers: 2
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174001
          - 123e4567-e89b-12d3-a456-426614174002

    - name: Management Approval
      types: ['Majority', 'Minimum']
      default: Majority
      minReviewers: 1
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174003
```

### Pre-Assigning Notifiers

You can also pre-assign notifiers to open stages using a `notifyList` block. Notifiers are added to the stage's notify list when the change order is created but do not participate in the approval process.

A `notifyList` accepts two arrays:

* `users` — internal users, specified as UUID strings (same format as `reviewers.users`).
* `emails` — external recipients, specified as plain email addresses. Use this for people who do not have a Duro account.

```yaml
stages:
  open:
    - name: Engineering Review
      types: ['Unanimous']
      default: Unanimous
      minReviewers: 2
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174001
      notifyList:
        users:
          - 123e4567-e89b-12d3-a456-426614174004
        emails:
          - supplier@example.com
```

{% hint style="info" %}
`reviewers.users` and `notifyList.users` are **internal-only**: each entry must be the UUID of a user in the library's organization. External addresses belong in `notifyList.emails`. To look up a user's UUID, query your organization's members — see [RBAC → Get Organization Members with Roles](/advanced-topics/rbac.md#get-organization-members-with-roles).

Uploading a template via the GraphQL API requires UUIDs in these arrays. The web template editor also lets you type email addresses for internal users and resolves them to UUIDs on save, so you only need to look up IDs when authoring YAML by hand.
{% endhint %}

#### Editor vs. API: participant values

The structure is identical for both authoring paths — only the participant values differ:

```yaml
# Web template editor — type email addresses; resolved to org users on save
reviewers:
  users:
    - jane@acme.com
```

```yaml
# GraphQL API / direct YAML upload — user UUIDs required
reviewers:
  users:
    - 123e4567-e89b-12d3-a456-426614174001
```

In the editor, unrecognized addresses in a `notifyList` are kept as external `notifyList.emails` recipients. The examples throughout this guide and the [reference](/library-configuration/change-order-workflow-reference.md) use UUIDs, since they're written for direct API upload.

### Approval Types Explained

* **Unanimous**: All reviewers must approve
* **Majority**: More than 50% of reviewers must approve
* **Minimum**: At least the minimum number of reviewers must approve

## Adding Validations

Field validations ensure data quality and completeness:

```yaml
fields:
  - name: estimated_cost
    type: currency
    label: Estimated Cost
    validations:
      required: true
      min: 0
      max: 1000000

  - name: part_number
    type: text
    label: Affected Part Number
    validations:
      pattern: "^[A-Z]{3}-\\d{4}$"
      required: true
```

## Automating Resolutions

Configure automatic actions when change orders are approved, rejected, or withdrawn:

```yaml
resolved:
  resolutions:
    onapproval: [AUTO_CLOSE]      # Automatically close when approved
    onrejection: [MANUAL_CLOSE]   # Require manual closure when rejected
    onwithdrawal: [MANUAL_CLOSE]  # Require manual closure when withdrawn
```

## Best Practices

### 1. Start Simple

Begin with a basic workflow and add complexity as needed. It's easier to expand a working workflow than debug a complex one.

### 2. Use Descriptive Names

Choose clear, meaningful names for stages and fields:

* ✅ Good: `manufacturing_impact_assessment`
* ❌ Avoid: `field1`, `stage_a`

### 3. Group Related Fields

Organize fields into logical groups to improve the user experience:

```yaml
groups:
  - name: Impact Analysis
    icon: mdi-chart-line
    fields:
      - name: schedule_impact
      - name: cost_impact
      - name: quality_impact
```

### 4. Document Your Workflow

Always include a clear description:

```yaml
description: |
  Engineering change workflow for hardware modifications.
  Requires technical review followed by management approval
  for changes exceeding $10,000 in impact.
```

### 5. Test Thoroughly

Before deploying a new workflow:

1. Create test change orders using the workflow
2. Verify all stages execute correctly
3. Confirm notifications reach the right people
4. Test edge cases (rejections, withdrawals)

## Common Patterns

### Pattern 1: Cost-Based Escalation

For organizations where higher-cost changes need additional approval:

```yaml
stages:
  open:
    - name: Initial Review
      types: ['Majority']
      default: Majority
      minReviewers: 2

    - name: Executive Approval
      types: ['Minimum']
      default: Minimum
      minReviewers: 1
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174003
```

### Pattern 2: Department-Specific Reviews

When different departments need to review changes:

```yaml
stages:
  open:
    - name: Engineering Review
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174001
          - 123e4567-e89b-12d3-a456-426614174002

    - name: Manufacturing Review
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174005
          - 123e4567-e89b-12d3-a456-426614174006

    - name: Quality Review
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174007
          - 123e4567-e89b-12d3-a456-426614174008
```

## Creating Templates via the GraphQL API

You can create and manage change order templates programmatically using the GraphQL API through Apollo Studio, Duro's interactive API explorer. This approach is useful for:

* Testing and validating your workflow configurations before deployment
* Creating templates across multiple libraries
* Version controlling your workflow configurations

### Prerequisites

Before you begin, you'll need:

1. **A Duro API Key**: Navigate to `https://durohub.com/org/@<your-org>/libs/<your-library>/settings/api-keys` to generate one. See [Getting Started → Authentication](/getting-started/authentication.md) for more information.
2. **Your YAML workflow template**: Either use one of the default templates or create your own custom configuration

### Step 1: Prepare Your YAML Configuration

First, create your workflow template YAML file. Here's a starter template:

```yaml
version: '1.0'
description: Engineering Change Review Process
schema_type: change_order_scheme

details:
  info:
    groups:
      - name: Change Information
        icon: mdi-information
        fields:
          - name: change_description
            type: longtext
            label: Change Description
            description: Detailed description of the proposed change
            validations:
              required: true

          - name: impact_assessment
            type: enum
            label: Impact Level
            description: Estimated impact of this change
            options:
              - label: Low Impact
                value: low
              - label: Medium Impact
                value: medium
              - label: High Impact
                value: high
            validations:
              required: true

stages:
  open:
    - name: Engineering Review
      types: ['Unanimous', 'Majority']
      default: Majority
      minReviewers: 2
      reviewers:
        users:
          - 123e4567-e89b-12d3-a456-426614174001

resolved:
  resolutions:
    onapproval: [AUTO_CLOSE]
    onrejection: [MANUAL_CLOSE]
    onwithdrawal: [MANUAL_CLOSE]

closed: {}
```

### Step 2: Minify Your YAML

Apollo Studio requires the YAML to be provided as a single-line string. To convert your YAML:

1. **Visit the YAML Minifier**: Go to <https://onlineyamltools.com/minify-yaml>
2. **Paste your YAML**: Copy your YAML configuration and paste it into the left input box
3. **Copy the minified output**: The right side will show your minified YAML as a single line. Copy this entire string.

![YAML Minifier showing conversion from formatted to minified YAML](/files/sXdf7oXfKJklwAVy7mmo)

### Step 3: Open Apollo Studio

1. **Navigate to Apollo Studio**: Open <https://api.durohub.com/graphql> in your browser
2. **Set up headers**: Click on the "Headers" tab at the bottom of the Operation panel and add the following required headers:

| Header           | Value                    | Description                                    |
| ---------------- | ------------------------ | ---------------------------------------------- |
| `x-api-key`      | `your-api-key`           | Your API authentication token                  |
| `x-organization` | `@your-org`              | Your organization slug                         |
| `x-library`      | `@your-org/your-library` | The library where the template will be created |

![Apollo Studio Headers tab showing x-api-key configuration](/files/NVD9dvIUQq40DkQLZQSu)

### Step 4: Create Your Template

1. **Paste the mutation**: In the Operation panel, paste the following GraphQL mutation:

```graphql
mutation CreateTemplate($input: CreateTemplateInput!) {
  changeOrders {
    createTemplate(input: $input) {
      id
      name
      config
      library {
        id
        name
      }
      createdAt
    }
  }
}
```

2. **Set up variables**: In the Variables panel, create your input object:

```json
{
  "input": {
    "name": "My Engineering Review Process",
    "configYAML": "YOUR_MINIFIED_YAML_HERE"
  }
}
```

Replace `YOUR_MINIFIED_YAML_HERE` with the minified YAML string you copied from Step 2.

3. **Execute the mutation**: Click the "CreateTemplate" button to run the mutation

![Apollo Studio showing the complete setup for creating a change order template](/files/fkE2K4iDuhtKlPj4shDP)

### Step 5: Verify Your Template

A successful response will show:

```json
{
  "data": {
    "changeOrders": {
      "createTemplate": {
        "id": "123e4567-e89b-12d3-a456-426614174001",
        "name": "My Engineering Review Process",
        "config": {
          "version": "1.0",
          "description": "Engineering Change Review Process",
          // ... rest of your configuration
        },
        "library": {
          "id": "fc28b204-0cd0-46b3-96eb-b0720c16c423",
          "name": "Main Library"
        },
        "createdAt": "2024-01-15T10:30:00Z"
      }
    }
  }
}
```

Your template is now created and ready to use in your change order workflows!

### Troubleshooting Common Issues

#### YAML Formatting Errors

If you receive a YAML parsing error:

* Ensure your YAML is valid before minifying (use a YAML validator)
* Check that the minified string is properly copied without line breaks
* Verify all quotes and special characters are properly escaped

#### Authentication Failed

If you get an authentication error:

* Verify your API key is correct
* Ensure the `x-api-key` header is properly set in the Headers tab
* Confirm your API key has the necessary permissions

#### Invalid Configuration

If the template configuration is rejected:

* Review the error message for specific validation issues
* Ensure all required fields are present in your YAML
* Verify user IDs are valid UUIDs belonging to your organization

#### Participant Validation Errors

When a template includes `reviewers.users` or `notifyList.users`, Duro validates the user IDs at upload time:

| Error Code                                | Cause                                                                          |
| ----------------------------------------- | ------------------------------------------------------------------------------ |
| `TEMPLATE_PARTICIPANT_INVALID_USER_ID`    | User ID is not a valid UUID or does not exist                                  |
| `TEMPLATE_PARTICIPANT_WRONG_ORGANIZATION` | User exists but is not a member of the library's organization                  |
| `TEMPLATE_PARTICIPANT_MALFORMED_CONFIG`   | Structural error (e.g., `reviewers` is not an object, `users` is not an array) |

External `notifyList.emails` entries are not validated against organization membership — any well-formed email address is accepted.

## Participant Population Behavior

When a change order is created from a template that includes pre-assigned reviewers or a notify list, Duro automatically populates the corresponding stages — adding `reviewers.users` as stage reviewers, and `notifyList.users` / `notifyList.emails` to the stage's notify list.

### Validation at Upload vs. Creation

Participant validation happens at two points with different behavior:

* **At template upload** (strict): All user IDs must be valid UUIDs, exist in the system, and belong to the library's organization. The template is rejected if any user fails validation.
* **At change order creation** (lenient): Valid users are added to their stages. Invalid or missing users are skipped, and warnings are logged to the change order's activity feed.

This two-phase approach ensures templates stay clean while allowing change orders to be created even if a user has been removed from the organization since the template was last updated.

### Activity Feed Logging

When participants are skipped during change order creation, Duro logs a `template.participants.skipped` activity entry containing the skipped user IDs, their intended stages, and the reason (not found or wrong organization).

## Next Steps

1. Review the [Change Order Workflow Reference](/library-configuration/change-order-workflow-reference.md) for complete specification details
2. Explore example templates in your library's configuration
3. Start with a default template and customize it for your needs
4. Test your workflow with a pilot group before full deployment


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.durohub.com/library-configuration/change-order-workflows.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
