# Welcome to ION

Supercharge your manufacturing with ION.

## What is ION?

ION is the Factory OS for next-generation hardware companies. It allows you to manage your dynamic manufacturing process and have traceability from design through delivery. It also puts the power in your hands. With ION's modern interfaces, individual teams can understand and plan the manufacturing workflow and stay on track for the company's overall product delivery goals.

### How can I use ION?

ION is for anyone working in, upstream from, or downstream from the manufacturing process. Below are some ways that you can use ION, based on your role.

#### Design Engineering

If you are a design engineer that spends time designing hardware and specifications for how hardware is going to be built or tested, you can use ION to manage your build and test procedures for use in manufacturing. While you might not be in the factory day in and day out, ION lets you rest easy knowing *which* procedures are being used in production because version and change control is built into procedures. See **version control** for details.

#### Production **T**echnicians and Operators

ION is the technician and operator's daily tool. Technicians and operators can get to work fast on delivering value to the company's product right from the ION **dashboard**. The dashboard presents the day's work, in priority order, and assigned to you. It also lets you and your team plan its workflow by assigning runs and work based on bandwidth, priority, and skills. Technicians can also communicate issues on the floor directly within ION instead of having to hunt down supervisors.

#### Manufacturing Engineering

ION allows manufacturing engineers to manage the flow of the manufacturing process with powerful **scheduling** and **resource management**. Rather than spending precious time reacting to downtime, issues tickets, and engineering requests, ION allows manufacturing engineers to spend time coordinating and optimizing the manufacturing flow and gathering meaningful insights to help improve the overall product design.

#### Quality Engineering

ION provides a data platform that allows Quality Engineers with the data they need to analyze manufacturing quality and create actionable insights for upstream design and process improvements. Rather than wrangling disparate datasets from different teams, ION gives access to both engineering (torque, voltages) and production data (shifts, machines, sensors) so that Quality engineers can analyze and create actionable insights for their company.

**Purchasing and Supply Chain Specialists**

Purchase parts, manage inventory, and send components into the manufacturing process in the same system building your parts. Supply chain specialists can manage suppliers and ensure high quality using rich data from the factory floor.

**CXOs**

ION Analytics creates a standard interface for your analysts to quickly pull data, build reports, and signal high-level issues directly to managers and bottom-line business owners.


# Features


# Procedures

Instructions for work to be done

## What is a procedure?

Procedures are ways to record work instructions, data collection, and workflow in ION. Procedures are made up of **steps** and their child steps that define what work is to be done and what data is to be collected. The execution of work is not done from this part of ION - it is done in a [`Run`](/features/runs).

Users must have the permissions `CreateProcedure` and `UpdateProcedure` create and release a procedure.

![Procedure edit view](/files/znhkIiJDnAeAPPnoUWQg)

## Creating a procedure

To create a procedure, go to the Procedures section in IO&#x4E;*.* You will see a list of procedures created at your company. Click **New procedure** to create a new procedure.

Enter the *title* and *description* of your new procedure. Don't worry, you can change these while your procedure is still in draft.

Select a procedure type. Build, Maintenance, Test, and Inspection Procedures have the same functionality, with one exception -- an inspection procedure can be used in an inspection run, which would be automatically created at the time of receipt of Purchase Order[ while using the workflow here](https://manual.firstresonance.io/features/purchasing/receiving-inspection#inspection-runs).

## Updating a procedure

Only procedures that are in **draft** can be update&#x64;**.** Once a procedure has been released, that version can no longer be modified. To modify a procedure, go to the Procedures section and select a procedure to modify. Now, you can modify the procedure's steps, attachments, and data collection fields.

### Steps

Procedures can have multiple steps. Each step has its own content, attachments, and fields. During a run, each step will be presented in the Technicians view in sequence.

## Versions and Archiving

Procedures are version-controlled, and runs use *specific* versions of procedures, so that the exact procedure that was used in production is always traceable. There can only be one version of a procedure in draft for a given procedure. From a released or archived procedure, you can "Create new draft", which will create the next incremental procedure version in draft.

<figure><img src="/files/0jbotBmu9k2Ytg9ACp64" alt="" width="277"><figcaption></figcaption></figure>

You can archive a procedure using the status icon in the top right. Archiving is useful for making sure a procedure does not get utilized in all runs going forward. We recommend this only when you are sure a procedure will never be needed again. When a procedure is archived, it will be removed from the procedure screen and from the run creation screen as an option. Archived procedures can be viewed by clicking `show all versions` from the procedures home page.

<figure><img src="/files/uqLdvPgPDuyHyn6NW7IU" alt="" width="169"><figcaption></figcaption></figure>

All versions that stem from a procedure will be part of the same Procedure Family.

<figure><img src="/files/XSwD8M2wnIolTyQ6NCPU" alt="" width="273"><figcaption></figcaption></figure>

## Reviews

{% hint style="info" %}
Contact your Customer Success Manager to enable role based reviews
{% endhint %}

When you are done updating a new version of a procedure, you can submit it for review. In the procedure action selector, select "For review". From there, you can add the roles and approvers who should review the procedure.

<figure><img src="/files/h347g314pJJrjhhPfxri" alt="" width="260"><figcaption></figcaption></figure>

Approvers will see the pending review requests in their home dashboard. Clicking into the review request will take the reviewer to the procedure to leave a review. Once all reviewers have *approved* the procedure, it will be automatically set to "released" so that it can be used in production runs.

{% hint style="info" %}
You can configure required approval roles in Organization settings exclusively in the new ION Experience. See URLs below to configure your approvals.
{% endhint %}

**Production Public:** <https://app-v2.buildwithion.com/settings/production/procedures>\
**Sandbox Public:** <https://app-v2.staging.buildwithion.com/settings/production/procedures>\
**Production Gov:** <https://app-v2.gov.buildwithion.com/settings/production/procedures>\
**Sandbox Gov:** <https://app-v2.staging.gov.buildwithion.com/settings/production/procedures>\
\
\&#xNAN;*Australian customers can take the above links and replace `.gov` with `.ap` and European customers can replace `.gov` with `.eu`*

\
Navigate to Settings > Procedures > Reviewer Roles. You can configure which roles and how many approvals from each of the roles is required to for the procedure to be released.

<figure><img src="/files/VAgfmbvBIFtmqjloC9vI" alt=""><figcaption></figcaption></figure>

This configuration requires 2 Engineers to approve the Procedure for it to get released. Required Roles appear in the "Required approvers" section in the Reviews tab of Procedures.

<figure><img src="/files/VyuAvPPQ6ytHufW4YyBS" alt="" width="375"><figcaption></figcaption></figure>


# Steps

Steps are ways to split up work instructions in a **Procedure**. Each step can represent a specific job to be done or action to take.

![All steps for a procedure are shown in a list on the left. The selected step's content is shown on the right.](/files/2cEKryGHPaN2xTqiX4ZT)

## Creating a Step

When editing a procedure, you can add a new step using the **Add Step** button or use the inline controls over existing steps to add a new step or new child steps. ION will prompt you for the new step's name and type of step.

![Step creation interface](/files/N1Mne9GwZcxLuKBRUeCU)

There are two main types of steps, Content and Datagrid.

## Copying Steps

When adding a new step, type in the title of the step you want to copy. ION will automatically fetch all existing steps that match the step title and display them along with information about what procedure they will be copied from. Hit **enter** to select the highlighted step or select the one you want with the mouse

![Step copy interface](/files/OZ9W2KBWlwbCekgGE21o)

You can also duplicate steps from the step list in a procedure using the **duplicate** tool by mousing over a step.

## Child Steps

Steps may be nested under each other to form parent-child relationships. This is useful for when you want to group multiple actions together, like inspecting multiple parts of a complicated assembly. Create child steps by using the **add child step** tool when mousing over a step, or by dragging an existing step under another step.

{% hint style="warning" %}
Steps may only be nested one level deep
{% endhint %}

Steps show the number of child steps they have on badge next to the step title.

![Step 2 has three child steps](/files/bRliKlpXXyQV7lhxmEVH)

## Re-organizing Steps

Use the handles on the left side of step tiles to reorder steps.

{% embed url="<https://www.loom.com/share/650c0164260e4feeb18ad500c486c6bc?sid=12b85f93-7234-4951-864f-b72ef03a0a75>" %}
Reorganize Steps and Child Steps
{% endembed %}

## Numbering Steps

Steps are automatically numbered starting from 0 based on their order. Child steps are numbered based on their parent step using dot notation. For example, the first child step of step 1 would be 1.0, the next would be 1.1 and so on.

## Step Locations

Each step can be tagged with a [**location**](/features/locations) under the "Select a workcenter" dropdown to indicate where it is to be done, like "Testing Lab" or "Paint booth 1 ".


# Content

Content steps are for written instructions. The content box supports text formatting features like colors, lists, fonts, pictures and tables.

{% hint style="warning" %}
When using **tables** in steps, we recommend setting them up in Google Sheets and pasting them in. Using Excel is not as reliable because formatting isn't copied over, but the content will still work.
{% endhint %}

![The step content editor](/files/yeVqLsFXpr55it3OMP1O)

## Dynamic Media

Use the dynamic media editor to make complicated diagrams with pictures, arrows and callouts. Unlike making diagrams with external programs, dynamic media in steps is not "baked in" can be edited at any time.

![Using the dynamic media editor to call out picture details](/files/G0uoK9vsP50hD5Cvpkhg)

## Fields

In addition to written instructions, procedure editors can also add data collection fields. Data collection fields can be filled out in [Runs](/features/runs) when they are created from Procedures. Fields can be named, reordered and set as required or optional. See the [Fields](/features/procedures/steps/fields) page for a full list of data types that can be collected.

![Field editing interface](/files/3QtgY2hqiwvgzwni17Cr)

## Assets

Assets are miscellaneous files that can be added for reference in a step.

{% hint style="info" %}
Pictures inserted into step content are automatically added to assets
{% endhint %}

![Assets list for step](/files/XjK9bqQiGdhxzEVywEfE)


# Datagrid

Datagrid steps are ways to collect tabular data. Each cell in a datagrid is a field that can be filled in by a user when the Procedure is made into a Run.

{% hint style="info" %}
See the full list of supported field types in the [Fields](/features/procedures/steps/fields) page
{% endhint %}

![Datagrid step editor](/files/3VfRqvuquukUBP9Wrh68)

## Datagrid Columns

The Datagrid can support any number of columns. Each column can be configured with a name and data type. Columns can also be set as view-only so they cannot be edited when the step is executed in a Run.

![Datagrid step menu](/files/3mALLTwP1UvqIfuJCmA5)

## Datagrid Rows

The Datagrid can support any number of rows. The **Required** toggle can be used to require rows be filled in when the Datagrid step is executed in a Run.

## Importing Datagrid Information

The Datagrid editor supports import of data from a CSV or Excel file. Configure the Datagrid columns to match the data you want to import, then hit the **Import** button to launch the import tool.


# Fields

## Data collection fields

You can include data collection fields that you want to collect when the Procedure gets executed in a Run. For example, let's say you want to know the *running torque* value for every run that uses a given Procedure. You can define that field in the procedure, and the technician/operator will input that when she/he executes the run.

#### Datetime

The date and time for a certain event. Use this field to track events and their times in production. For example, if you want to track when something was put into a thermal oven.

#### Boolean (checkbox)

True or false. This gives the operator a simple option for whether something is true or false. For example, use this field for a simple pass/fail data collection.

#### String (text)

A simple text field data collection field. Useful for freeform responses from the factory floor.

{% hint style="info" %}
String fields have no length limitation and support all UTF-8 characters.
{% endhint %}

#### Number - includes the unit for data collection

Similar to a string, except this field type enforces that the data collected is a numerical value. Unlike other fields, number fields can have calculations, i.e. validations. See the Validations section below for more information on how to use validations to automate checking values in operation.

#### Select

Use this to provide a list of options to select on the floor. The select field only allows *one* response. For more responses, use multiselect.

#### Multiselect

A list of options which allow for more than one items to be selected in operation. This is useful if you want to collect multiple attributes or conditions from the operator. For example, "scratched", "bent", and "discolored" can all be multiselect options, and it might be that the operator found all three attributes to be true.

#### Signoff

Signoff fields allow procedure builders to define signoffs required on a step to ensure quality. Signoffs are defined by role, which is then enforced during the Run. For example, a procedure builder can define a Procedure step requires someone with the Quality Inspection role to signoff before continuing. During the run, Quality Inspector Susie can signoff on the step, but Assembly Technician Michael cannot. ION maintains that Susie signed off on the field with a digital signature.

Signoff fields can be configured as *Peer Review Only* which means only users that have not worked on the run connected to the signoff field can complete the field.

As a workspace admin, you can manage which roles exist in your organization and who has which roles in your [organization settings](/features/application-settings#organization-settings).

#### File attachment

Use this to attach a file. You can, of course, use the attachments in the run step, which is a lot more flexible and preferred. A file attachment field type can be useful when you know that you want a very specific file, such as a CSV upload from a machine or similar.

{% hint style="info" %}
The file attachment field has a maximum size of 5 gigabytes
{% endhint %}

#### Tool

Link use of [**Tools**](/features/tools) to a run step. Filling out a tool field on a run links records a use of the tool on the run for traceability and containment purposes. Tool fields can be limited to specific tool part numbers, types, and maintenance/calibration status of the tool.

#### ION: User

This links a user from your ION instance to a step.

#### ION: Part

This links a part from your ION instance to a step.

## Required Fields

By default fields are optional. Leaving a field blank on a run step will not block the user from completing the step. Procedure writers can set fields as **Required** to force the executing user to fill it out.

![Required setting on a field](/files/0qNRcXS4NdfcA4lWAsNA)

If a field is set as **Required**, it may also be set to allow **Not Applicable** entries. This can be used to provide positive confirmation by the user that they chose not to fill out the field.

{% hint style="info" %}
Fields completed with **Not Applicable** record their `value` as `null` but the `not_applicable` field as `true`
{% endhint %}

<div align="center"><img src="/files/9UbM1Nu1keSWXA33Yo5J" alt="Required field that allows not applicable entries"></div>

![User marking a field as Not Applicable in the Run Execution interface](/files/hzJpOg5Ga6hC4SPkwDJM)

## Field Validations

Number fields in ION allow for setting up validations, or calculations, to automate numerical checking out on the floor. This is very useful for setting up conditions for passing. For example, if a torque value must be within a certain range, such as greater than 5 ft-lb but less than 10 ft-lb, you can use validations to set up your limits. Validations automatically run when a value is input in a run. If you have the relevant [organization settings](/features/application-settings#organization-settings) for automatically creating an issue when a value exceeds the criteria, an issue will automatically be created in IO&#x4E;*.*

{% hint style="info" %}
Field validations may be only used for fields in **Content** steps.
{% endhint %}

![Setting up validations in the procedure fields definition](/files/-MAReGUiUjKqdtgXhUmX)

![Automatic indication when a value exceeds the setup validation criteria set in the procedure](/files/-MAReHzy1ctMR2zemKa4)


# Attributes

Add step attributes to categorize your procedure operations

Steps support [**Custom Attributes**](/features/custom-attributes) that can be used to add user-defined data fields to procedures. Step attributes are accessible thorough a tab in the step or run view.

<figure><img src="/files/bDU7ckIQMrj3bFtohTNB" alt=""><figcaption><p>Step attributes are editable when editing the enclosed procedure</p></figcaption></figure>

Use step attributes to add first-class data fields to steps. For example, you can add a boolean field that indicates that the step requires safety training before it can be executed.

Step attributes act like other data attached to steps like content, title and fields. Step attributes are editable when the procedure is editable and step attribute values are copied to run steps when procedures are used to make runs. Step attributes on run steps can be edited in a [Redline](/features/runs/redlining#starting-a-redline).


# Dependencies

You can manage complex dependencies in ion using the Procedure dependency manager

## The dependency manager

The Procedure dependency manager is right within a given procedure. Click **Dependencies** above the steps list and you will enter the dependency editor mode.

![Procedure dependency view](/files/NXQCEfFIlOv4OexAv8iA)

Click the ***i*** icon to get instructions on how to manage the dependencies. Dependencies are then enforced in the execution workflow, making it easy for operators/technicians to know which step is available next, which is blocked, being redlined, and more.


# Part-Procedure Relationship

Procedures may be associated with one or more parts to relate a workflow with a specific workpiece. Link a part and a procedure from the **Parts** tab on a procedure. Note that this isn't a parts list that are in an assembly - by setting this relationship you are telling ION which procedures are used to produce a certain part or assembly.

![Linked part interface](/files/NxF6LqP6JR6KuDRwPNjG)

You can also set up the part-procedure relationship from the parts library sidebar.

<figure><img src="/files/1iAjgoECnQdxabSYeql4" alt=""><figcaption></figcaption></figure>

When you link parts through this relation when you have the "Require part-procedure relationship to be approved" box checked in your organization settings, ION will not allow you to create runs unless the selected part is linked to the selected procedure.

![](/files/fVJLWgLJgVTNrw9lbzA8)

With this box checked, when you attempt to create a run with a procedure that is not linked to the selected part, you will get an error that looks like this:

<figure><img src="/files/rrRZGQf3ewe4QlCSVuBV" alt=""><figcaption></figcaption></figure>

#### Required vs. Optional Part Procedure Relationships

When linking parts to an inspection procedure, the **Required** or **Optional** setting determines whether an inspection run is automatically created upon receipt.

* This toggle **ONLY** effects **INSPECTION** type procedures their parts upon receipt.
* **Required:** When a part marked as *required* is received, an inspection run is automatically generated for that part according to the associated procedure.
* **Optional:** When a part marked as *optional* is received, no inspection run is automatically created. You can still initiate an inspection manually if needed.

This setting helps control which parts must go through inspection by default and which can be inspected at your discretion. See it in action below.

{% embed url="<https://www.loom.com/share/36a69ebc5462407894e8ee3deb86c2af>" %}


# Attributes

Create custom attributes for Procedures

Procedures support [**Custom Attributes**](/features/custom-attributes) that can be used to add user-defined data fields to procedures. Procedure attributes are accessible thorough a tab in the procedure view.

Much like procedure steps, procedure attributes are copied to run attributes provided the run attribute has the same name. For example, if both procedure and run have an attribute called "Department", on creation the Run attribute would inherit the value of the procedure attribute when created.

![Editing Custom Attribute values in a procedure](/files/XWbVmtxverkMYAVC6XoJ)

{% hint style="info" %}
Procedure custom attributes can be edited at any time
{% endhint %}


# Standard Steps

In a manufacturing environment, it's common to build up standard processes for working with similar parts. For example, all parts built out of a certain material my need an extra inspection method to make sure they haven't been damaged in production. It can be tedious to copy and paste the same instructions between many different procedures and introduces a risk that the instructions may not be copied correctly. In addition, changing the instructions in one place means you have to go find everywhere a process is used to ensure it is up to speed.

**Standard Steps** are designed to combat this problem by introducing a new type of step that can be shared between procedures. Standard steps can be independently revisioned from procedures. When a standard step is updated, it is automatically updated in all procedures and runs where it is used.

{% hint style="info" %}
Standard steps are called out with blue **S** icon or the words **Standard Step**
{% endhint %}

## Creating Standard Steps

Navigate to the standard steps view by clicking on Procedures in the sidebar. Standard Steps is displayed as a sub-heading of Procedures. You can navigate standard steps using both a card view and a list view.

![Standard Step card view](/files/8uYBcnVX1GcvOD4P8vp2)

The creation interface for standard steps is very similar to the Procedure creation interface, but there is no dependency editor or or part linker. Only one step is shown. Edit the standard step as you would a regular step. You can also optionally add child steps for longer more complicated operations, but you cannot add a standard step as a child step.

![Standard step edit interface](/files/Sl809KPxFIvgxMMMzU51)

Standard steps use the same review process as procedures. To release a step, change its state to **Review** and add reviewers as required. When all reviewers have signed off, the step switches state to **Released** and may be copied into procedures and runs.

## Using Standard Steps

You can use standard steps in any place a regular step can be used. When creating a new step in a procedure or in a redline, enter the name of the standard step and select it from the step copy dialog.

![Copying a standard step into a procedure](/files/A3WzzftcePJImVEfBne4)

Standard Steps can be also used as child steps to standardize one part of a larger action.

![Standard step used as a child step](/files/HkR1vGtG1efI3Effonyn)

Standard Steps in Procedures and Runs **will display the content of the most recently released version**. For example, if you used version 1 of a standard step in procedure A and then released version 2 the standard step in procedure A will automatically update to reflect the changes in version 2.

After a standard step in a Run has been started, it will "disconnect" from the main standard step and stop updating. This is to maintain the Run's purpose as an accurate record of what actions were done.

## Executing Standard Steps in Runs

{% hint style="info" %}
**Initializing** is when the step takes on details of the latest released version the standard step and will not receive further updates.
{% endhint %}

You can execute a standard step the same way you execute a regular step in a Run. Standard steps **initialize** when the Status moves to any of the following:

* IN PROGRESS
* REDLINE
* CANCELED
* FAILED
* COMPLETED\
  \
  At that time, the details of the standard step will be updated to reflect the latest released version. This is indicated by the version you will see in the step queue and near the step title.

<figure><img src="/files/p5MzvmBTuXFIJxjhijRz" alt="" width="325"><figcaption></figcaption></figure>

Another indicator appears in the header of the run step. When you see the “linked” icon, it means the standard step will continue to receive updates if a new version is released.

<figure><img src="/files/Fw6UxLhxyObaf5r5QD3N" alt=""><figcaption></figcaption></figure>

If you see the “broken link” icon, the standard step is frozen because one of the statuses above was used at some point in its history, which prevented further updates.

<figure><img src="/files/dhs60NYtUuA09IGDcVFW" alt=""><figcaption></figcaption></figure>

**Initialization** also occurs when a standard step is redlined into a run. For example, if you add Version 2 of the standard step 'Torque Bolt' to a run, it will always remain as Version 2. Even if the redlined step is not started, 'Torque Bolt' will not inherit any new versions.

### Approvals

{% hint style="info" %}
Contact your Customer Success Manager to enable role based reviews
{% endhint %}

When you are done updating a new version of a standard step, you can submit it for review. In the standard step action selector, select "For review". From there, you can add the roles and users or teams who should review the procedure.

<figure><img src="/files/rYUeZMoCbnoeapppzti7" alt="" width="388"><figcaption></figcaption></figure>

Approvers will see the pending review requests in their home dashboard. Clicking into the review request will take the reviewer to the standard step to leave a review. Once all reviewers have *approved* the standard step, it will be automatically set to "released".

#### Required Approvers

Required approvers can be configured through the API only (for now).

```graphql
mutation createStepApprovalRole($input: CreateStepApprovalRoleInput!) {
  createStepApprovalRole(input: $input) {
    approvalRole {
      _created
      _etag
      _updated
      count
      createdById
      gateType
      roleId
      updatedById
    }
  }
}

{
  "input": {
    "roleId": 3,
    "count": 1,
    "gateType": "RELEASED"
  }
}

```

This configuration requires that 1 user with `roleId` of 3 approves the standard step for it to be released. These reviewers will appear in the "Required approvers" section of the Review modal.

<figure><img src="/files/UdtcJeZugKh4AA295AtC" alt="" width="391"><figcaption></figcaption></figure>


# Installation Requirements (Beta)

Assign and enforce parts to be installed from your mBOM to a particular step in a procedure

Before implementing installation requirements, please review the Best Practices below!

### Pain Points and **Use Case**

Have you ever been close to the end of an assembly or worse, needed to investigate a part that has been installed only to realize that the digital aBOM doesn't reflect the state of the physical build? Do you spend valuable time at the end of your build cycle or in deep investigations to rectify these differences?\
\
Now you can assign required installations at each step in a given procedure. This will prevent the run step from closing until all of the required installations are complete, similar to required fields. When a run is closed, you will have the utmost confidence that the aBOM digitally represents your physical assembly.\
\
Not only does this mean that you can trust run execution will occur correctly, but you can also build your procedure faster by understanding at a glance which components you have digitally assembled and what remains. Take an example where you have hundreds of fasteners to install. With this feature, you can ensure that from the procedure, all of the fasteners are assigned to a step before releasing the procedure.

## Step Assignments

The part assignment view is split into two distinct sections. The top section represents installation requirements assigned to the step that is currently selected via the procedure step queue. The bottom section represents the selected part's selected mBOM version.

<figure><img src="/files/9glOxq3K9NVHhrQh9JNT" alt=""><figcaption></figcaption></figure>

To add assigned installs to the step that is currently displayed in the procedure window, select the + button next to the mBOM item on the bottom right of the panel.

<figure><img src="/files/uQoWEBgh9SHj1GRitmXp" alt="" width="364"><figcaption></figcaption></figure>

{% hint style="info" %}
The quantity assigned is the minimum required installation quantity to complete a run step.
{% endhint %}

When you have installation requirements assigned to a step, they will show up in the upper half of the panel. mBOM items can be partially assigned to steps. The formatting is represented as Qty Assigned to Step / Total Quantity in mBOM (Unit).

<figure><img src="/files/dKEtcWnbArlFxge37n9a" alt="" width="363"><figcaption></figcaption></figure>

{% hint style="info" %}
When creating a run, you can only create a run against the latest released mBOM version, or if none are released, than the latest draft. Please ensure you release mBOMs as needed to be used in runs.
{% endhint %}

We recognize there will be situations to release a procedure for a released mBOM while drafting up a future version of the same mBOM. Please keep the above note in mind when building procedures.

<figure><img src="/files/h9r57BMoDyn1YtQMdKRQ" alt=""><figcaption><p>v4 mBOM is in Review</p></figcaption></figure>

Once mBOM items have been completely assigned, they will shaded green on the mBOM panel if the "Show All" toggle is on. With the "Show All" toggle off, completely assigned mBOM items will be removed from the view for a more streamlined assignment process.

<figure><img src="/files/onkNNVxJCYg8tXG6K3i1" alt="" width="375"><figcaption></figcaption></figure>

### Substitutes

The crossing arrows highlight substitutes on the mBOM, showing what other parts are listed as substitutes.

### Reference Designators

Similar to assigning the minimum quantity to close a step, you can also assign reference designators that are required to close a step.

<figure><img src="/files/k0Zr5X2nv9ScHJViQtta" alt="" width="563"><figcaption><p>Select which reference designators are needed on which step</p></figcaption></figure>

## Installing Inventory on Run Step Installation Requirements

Similar to installing inventory on the aBOM, now it is much more accessible from the run step itself.

{% embed url="<https://www.loom.com/share/7cf2a7d524784c839dfd1216555d1027?sid=5b2e3079-2b8a-4f4a-a4f2-8b88ffd9ebe2>" %}

You will not be able to complete a step until all run step build requirements have their minimum quantities and reference designators satisfied. The inventory list will include any available substitutes.

## Permissions

To create, update, and delete installation requirements on procedures, please grant yourself a role with `StepPartRequirement` permissions.

## Modifying your mBOM

Oftentimes, your mBOM changes even after you have released a procedure. Our aim is to prevent you from having to manipulate the procedure in as many cases as possible so you can make changes on the fly. Here is how ION handles the different types of changes on a mBOM.

#### No Changes to the Procedure are Required:

* Removing a part:
  * This removes the associated installation requirements from associated procedures. This will mean you can safely remove parts without needing to revise the procedure to effect those changes.
* Updating the part number on an existing mBOM requirement:
  * This will update all installation requirements in associated procedures automatically with the new part number.
* Updating the name of a reference designator:
  * This will update all installation requirements in associated procedures automatically with the new reference designator if called out.
* Adding substitutes:
  * All installation requirements will now show those new substitutes.

#### Procedure Revision Required:

* Adding a part:
  * There is no impact on associated procedures.
* Updating the quantity of an mBOM requirement:
  * You cannot reduce the quantity past what is assigned to a procedure. In this instance, you will need to create a new procedure and then up version the mBOM as well.
  * You can increase the quantity with no impact on associated procedures.

{% hint style="info" %}
In every case, there is no impact on existing runs and aBOMs at the time of change.
{% endhint %}

## Best Practices

1. Installs will not be propagated across batches.
   * Each batch is designed to ensure traceability for every run within it. Since you need to select the specific inventory you install, allowing installs across different runs would compromise this traceability and could lead to inconsistencies in inventory tracking. By restricting installs to individual runs, you maintain the integrity and accuracy of the manufacturing process.
2. You can only assign installation requirements on standard steps when they are called out in a procedure.
   * Each procedure is unique to a set of parts and mBOM versions, you can assign installation requirements on the procedure that calls out a released standard step. You cannot add installation requirements on standard steps when they are in a draft or any state.
3. The installation requirements on steps are a minimum requirement therefore, proper training is required with technicians.
   * If technicians continue to install through the aBOM manually, ION will ask them to install again to meet the minimum requirement needed to complete the step. Therefore it's best to train technicians to use installation requirements so this issue does not occur. Redlining is coming at a later date so if you are not confident that your procedures will change then we recommend setting the minimum installation requirement quantity to zero with the quantity needed listed on the step content itself to allow you to make changes as needed.
4. Redlining: At the moment, redlining of new part step requirements is not available. If you do not want to require installs on run steps because of the inability to redline, go into your Org Settings, and under runs, tick the box `Allow run steps to be complete without required install`.

### As-Required, Continuous Usage, and Consumables in Relation to Installation Requirements

#### You should only associate build requirements to steps when you are certain they will *always* be installed.

If a material will always be used during the execution of a step—but the exact quantity may vary—you should add it as a **0-quantity build requirement** on that step. This ensures technicians are prompted to record the actual usage without forcing a fixed amount.

**Example:**\
You always apply epoxy, but the amount differs each time.\
→ Add epoxy to the mBOM and associate it to the appropriate step with a 0 quantity.

#### Do not associate build requirements to steps when installation is optional or situational.

If a material is **not always installed**, do **not** attach it to a step. Instead, you may:

* Keep it in the mBOM without step association, or
* Add the build requirement to the aBOM during the run when needed.

**Example:**\
A shim is only occasionally required to level a plate.\
→ Leave it unassociated in the mBOM and add it to the aBOM only on runs where it is required.

#### Planned future behavior: optionality and redlining on runs.

In a future release, operators will be able to **redline build requirements directly on a run**, enabling optional materials within step associations. Until this is available, customers should follow the guidance above to avoid blocking steps with requirements that may not apply.

#### If you are blocked on a run due to required installs, you may temporarily allow steps to complete without them.

If a run cannot proceed because a required install was incorrectly assigned:

1. Have an admin toggle the organization setting\
   \&#xNAN;**“Allow run steps to complete without required install.”**
2. Update your procedure and build-requirement associations following the best practices in this section to prevent future disruptions.

## Coming Soon

1. **mBOM Importer improvements:** We want to improve how you import mBOMs to allow you to preserve as many connections with existing procedures as possible. This will enable you to make small changes to mBOMs without recreating all of your required installations on procedure steps.
2. **Parts Panel and Step Build Requirements Assignment Panel Workflow Improvements:** At the moment, to access the step build requirements assignment panel, you need to click through the parts panel on the procedure. We know that manufacturing engineers will spend more time on assigning mBOM items to steps and not adding top-level assemblies to the procedure. We'll make improvements to make these views more streamlined and accessible from the procedure.


# Nested Steps and Nested Standard Steps

Take your procedures to the next level.

### Pain Points and Value of the Solution:

Managing complex assembly processes often involves creating intricate dependencies between various sets of instructions, which can be challenging and time-consuming. Traditionally, users have struggled with the complexity of manually updating these procedures and managing dependencies, leading to increased risk of errors and inefficiencies. The old limitations in nesting both steps and standard steps have restricted the flexibility needed for detailed workflows, and the stop gap solution of manually redlining and merging changes has been cumbersome and prone to mistakes.

ION solves this pain with enabling complex assembly through nested standard steps and nested steps. By embedding standard steps within other steps, users can create comprehensive dependency graphs, ensuring a structured and interconnected workflow. The solution has the ability to capture the most finite process such as torquing a bolt to the most complicated integration process by combining many nested steps with one another. The ability to nest procedures infinitely provides the flexibility to accommodate complex workflows. Automatic updates and improvements to standard steps are reflected across all dependent runs, significantly reducing the need for manual redlining and merging processes. This feature also encourages the use of MBom for subassemblies, facilitating the installation of entire subassemblies without creating circular dependencies. Overall, this feature enhances workflow efficiency, ensures consistent application of improvements, and provides the flexibility needed for managing complex builds effectively.

{% hint style="info" %}
*Note: This feature is only available to those at the advanced or enterprise tiers. Please contact your CSM for more information.*
{% endhint %}

### Definitions:

<table><thead><tr><th width="158">Term</th><th>Definition</th></tr></thead><tbody><tr><td><a href="/pages/TJuHiM4bfNDbb0Bunwwf">Standard Step</a></td><td>A set of revision-aware work instructions that can be added to other procedures and standard steps. Each time a standard step is used, it automatically pulls in the latest released version of the work instructions, ensuring consistency across procedures and runs.</td></tr><tr><td>Procedure</td><td>A structured group of steps that serves as the basis for runs. Procedures are not revision-aware, meaning that once they are set in a run, they do not update automatically if revised. Procedures can be associated with specific parts and have part-step associations. They also allow for deeply nested steps, creating a detailed, customizable workflow.</td></tr><tr><td>Depth</td><td><p>This term describes the level of nesting within a procedure:</p><ul><li><strong>Depth 0</strong>: The root level of a procedure.</li><li><strong>Depth 1</strong>: Direct children of the root level steps.</li><li><strong>Depth 2</strong>: Children of steps in Depth 1, and so on.</li></ul><p>You can determine the depth by reviewing the breadcrumb trail at the top of the procedure's step queue.</p></td></tr><tr><td><a href="/pages/-M1cllXs9PwXeUpAUcSN">Dependency</a></td><td>A defined execution order between two or more steps at the same depth level within a procedure. Dependencies ensure that steps within the same level are completed in the correct sequence.</td></tr></tbody></table>

### Feature Walkthrough

{% @storylane/embed subdomain="firstresonance" url="<https://firstresonance.storylane.io/share/wch3ppdsuqbi>" linkValue="wch3ppdsuqbi" %}

### Best Practices for Nesting:

1. **Using Standard Steps:**
   * Standard steps should be used when a set of instructions is likely to be used multiple times across a variety of processes OR when it is critical that updates to a process are captured before execution. When selecting to use standard steps, you are making a conscious decision that any revision to that step will reflect the latest instructions in all places it’s used—whether in other procedures, standard steps, or runs.
2. **Single Parent Step Usage**:
   * Use a single main parent step to group similar steps with shared intent. This approach improves workflow organization and dependency management. For example, to standardize torque instructions, nest all related steps under a single step named “Perform Standard Torque Operation.” This consolidates related actions, enhancing clarity and control over grouped steps.
3. **Dependency Graph Creation and Procedure Nesting**:
   * To build a structured dependency graph, nest standard steps within each other. This allows for infinitely nested steps to manage complex workflows with interconnected steps. Create and edit dependencies for a standard step only at its root level to maintain consistency everywhere it is used.
   * Example: If a standard step like "Seal Hatch" includes another standard step, "Torque Bolts", then edit dependencies for "Torque Bolts" within its own root procedure. This ensures any dependency changes are reflected consistently wherever "Torque Bolts" is used.
4. **Version Control and Releases**:

   * Create and release standard steps to include them in procedures. Make changes to standard steps after initial runs to reflect improvements automatically across all to be started dependent runs, reducing the need for complex redlining and merging processes. Place runs on hold temporarily until all necessary instructions are versioned correctly to avoid starting incomplete procedures.
   * Example: If a run starts before the road test procedure is finalized, the run will automatically pull the latest version of the procedure (v2), streamlining improvements across all dependent runs without requiring manual updates.

   <figure><img src="/files/ZSn3cjLe4FB8wMAJyixw" alt=""><figcaption><p>Updating of standard procedures does not block work</p></figcaption></figure>
5. **Usage of MBom for Subassemblies**:

   * When setting up a Manufacturing Bill of Materials (mBOM), ensure that a specific instance of a procedure is connected only to one parent assembly to avoid circular loops in the dependency graph. Utilize the hierarchy and build your sub assemblies in their own procedures, not one massive "do everything" procedure. A procedure tied to a lower-level subassembly cannot also be tied to the parent assembly, maintaining clear and non-redundant relationships.

   <figure><img src="/files/OyReqEYvianrtUTUfLsT" alt=""><figcaption><p>Proper Use of Standard Procedure</p></figcaption></figure>
6. **Avoidance of "m states"**:
   * In the context of MBom setup, ensure that all inventory is real inventory rather than "m states." "m states" are manufacturing states, representing the state of the product rather than something physical that has been installed, uninstalled, or can exist in inventory. Avoiding "m states" prevents issues with parallelization and the complications that arise when uninstalling a process that already occurred, maintaining the integrity and accuracy of the inventory and processes. In addition, it gets your eBOM that much closer to matching your mBOM.
7. **Max Nested Step Depth of 5**
   * The limit on the number of nested layers you can create is 5. As procedures become more deeply nested, assess the complexity and clarity to ensure it remains manageable for the team. Consider setting internal guidelines on how deep you want your organization to nest steps to maintain an effective workflow. This change allows First Resonance to safeguard procedure creation via the API, that without restrictions could result in accidentally creating hundreds of layers of depth effecting system performance.

#### **Examples:**

High Level Integration and Final Check Procedure Setup With Nested Standard Step

<figure><img src="/files/hDbuIFmXJE2kMh5latul" alt="" width="563"><figcaption></figcaption></figure>


# Procedure Best Practices

This page will elaborate on the procedure features and demonstrate how to combine them to accomplish specific use cases.

## Use Case: Implementing Nested Steps

The purpose of this use case is to show how nested standard steps can be utilized in tandem with the hold status in runs. This combination ensures that high-level builds are executed sequentially and with the most up-to-date information. By placing certain steps on hold, you allow planners to schedule production work even when some process details are not fully defined.

The example provided will reference the diagram below, where the **purple bubbles** represent each step in the pathway to enabling this use case.

<figure><img src="/files/RctjVu7Yk1IuLD6wsxp3" alt="" width="375"><figcaption><p>Process Requirements to Complete a Car Build</p></figcaption></figure>

1. **Identify a process where nested standard steps can be helpful**
   * This can be a very high level situation such as final integration, testing, and delivery (as shown above).
   * Equally this can be a common process performed 10s of times a day such as securing body work which may involve standard steps like torquing, sealing, and inspecting.
2. **Identify the groups of work to be performed.**:
   * Start with a top-level procedure containing multiple standard steps. For example, assume you have four standard procedures within the top-level procedure.
3. **Evaluate Standard Steps**:
   * Evaluate each standard step:
     * If standard steps have completed work instructions and are released technicians can start working on those procedures.
4. **Create Placeholder for Incomplete Instructions**:
   * Some procedures may still be undefined and thus you will not want for work to begin on those steps within runs in which the standard step is called out.
   * Put a placeholder, hold, on the fourth standard step to prevent technicians from starting it prematurely.
5. **Put the Standard Step On Hold**:
   * Navigate to the standard step on the run that needs to be placed on hold and indicate that hold status
   * This blocks work from beginning until the work instructions are complete and valid for execution
6. **Release Hold When Updated Standard Step is Ready**:
   * Once the work instructions for the held procedure are finalized, release the updated standard step and take the run instance of it off hold.
   * Technicians can now start working on the procedure now that the instructions are finalized and updated within the run to reflect the latest released standard step.

<figure><img src="/files/KipDrqTg8U4HioNWwuce" alt="" width="563"><figcaption></figcaption></figure>

By integrating nested procedures with the hold feature, you can maintain workflow flexibility while ensuring that all necessary steps are completed in order.


# Runs

Runs are instances of activities in your manufacturing process

## What is a run?

A **Run** is an activity or activities in your manufacturing process. In a simple case, a run is an instance of a procedure acted out in the real world. Technicians or engineers execute runs on real hardware on the factory floor.

A run is made up of a list of **Run Steps**. When creating a run from a procedure, all the procedure steps will be copied into the run along with their dependencies.

## Creating a run

### Runs page

From here, click the green "Create runs" button in the top right of the page. ION will present a form that allows you to name the run, select the procedure to use for the run, set a due date, and assign it to someone at your company. You can also assign the run to someone at a later time. Once you create the run, it will appear as a new run that is in *Todo*.

You can also create runs in bulk via CSV, or bulk create them in the UI by clicking "Add Run". You can also make multiple copies of a run using the copy run button.

If you select a procedure for a run, it will be created with a copy of all the steps from the procedure. If you don't select a procedure it will be created with no initial steps. You can always redline in additional steps to a run after creation.

<figure><img src="/files/q5lYnTAhOq7xssMi0e9C" alt=""><figcaption></figcaption></figure>

### Setting the Inventory to Be Built

By default, choosing a part will create a new inventory for the run to build. You can optionally enter a serial or lot number. These can also be autogenerated. When this inventory is created, it will be created in `WIP` status to signify that it is being built and this inventory will be displayed on your inventory screen.

Alternatively, you can link an existing inventory if you have an existing part that is getting work added to it. Toggle the "Use existing inventory" option to choose an existing inventory. You can not link existing inventory that is `Scrapped` or `Unavailable`.

{% hint style="info" %}
You can also use the **Bulk create runs** button to create runs in bulk from an Excel sheet or CSV file.
{% endhint %}

### From the procedure

You can also create a run from a *released* procedure. Go to the procedure that you would like to use for a new run and select the "Create run" button next to the "Released" button. From here, *ion* will present a form to allow you to create a run. The procedure will be pre-populated in the run creation menu.

## Assigning a run

You can assign a run to an individual via the `Run Summary` page.

<figure><img src="/files/Zy57DyDTLrLhgzbhkLUn" alt=""><figcaption></figcaption></figure>

## Executing a run

If a run is assigned to you, it will appear in your "Todos" list on the main application home page. Clicking on that "todo" will take you right into the execution screen for the step you are assigned to. From here, you can move your step from "todo" to "in progress" , input all of the requested data for the run (as defined in the procedure) in this run step, and finally move the step to "complete". Marking a step as complete will automatically enter you into the next step in the the dependencies tree. There are also options to put steps "on hold" and in a "redline" state.

In addition, if you have an inventory (i.e. an assembly) that you have associated to the run and is being produced by the run, that inventory location will automatically updated according to the location of the run step that was most recently put in progress. This way, the inventory follows the locations of the run steps. If a location does not exist on a run step when it is started, than the inventory on the run will remain in it's previous location.

You can also assign runsteps to different people than who the run is assigned to in order to more effectively manage your factory.

On Hold means that you need to pause progress on that step and to let anyone who views the run that there is an issue that needs to be worked out.

Redline allows the editing of a step in the middle of the run by someone with the appropriate role. This allows you to edit a mistake in a procedure or add information to the step execution.

## Canceling a run

If you accidentally make a run or want to stop work on a run, use the **Cancel** option in the run menu. This will cancel all remaining steps in the run that are unfinished. If you change your mind you can change the step states from **canceled** back to a workable state.

![Cancel option in run menu](/files/QFcaqLS5TzFPwPpMgMCH)

## Archiving a run

If you want to hide a run from the runs list, archive it using the **Archive** option in the run menu.

{% hint style="warning" %}
**Archiving a run is permanent**
{% endhint %}

Here's a quick video below on how to archive a run.

{% embed url="<https://www.loom.com/share/279f99f7ee5c4fccbb8b94573f5153fa?sid=5337c3e2-567b-4061-b644-9f96439bfae1>" %}


# Run Execution Overview

This page outlines all of the changes in IONs new run execution view, rolled out 4/24/24.

For a walkthrough of the new streamlined features in run execution, check out this walkthrough:

{% embed url="<https://firstresonance.storylane.io/share/yjkyllpxnor6>" %}

Our plan will be to entirely replace our legacy view of ION with the new and improved Runs 2.0. The emphasis of this new version is to deliver performance and intuitive workflows for technicians, who have the highest touch point and throughput needs in ION. 2.0 will ensure that the software works for your production teams, and does not slow them down. Below is a list of improvements we have made and will continue to improve upon.

* Performance: Throughout the new execition, performance is embedded in every transaction. Try loading a large content step, or quickly updating a series of values in a datagrid and comparing that to the legacy view. You will see in many places up to 10x performance increases.
* Scrollable Run Header:

{% embed url="<https://www.loom.com/share/9b511ddea47c457ca4689f41b3954f5f?sid=663af729-e72c-4c00-b28c-f522d7ad861e>" %}

* File Viewer: View PDFs and image file types right in the application without having to download by clicking on the image's thumbnail to pull up the file viewer. You can flip through different images and pages in a PDF.<br>

  <figure><img src="/files/GgJshtImlSD6fXIaUs22" alt="" width="375"><figcaption><p>File Attachments</p></figcaption></figure>

  <figure><img src="/files/J5gtSQQDYscVq3Cihsgh" alt="" width="375"><figcaption><p>File Previewer in Application</p></figcaption></figure>
* Finger-Friendly Sizing: Our goal is for technicians who are using iPads or other touchscreen devices to be able to quickly and confidently interact with ION without being worried about clicking the wrong button or worse, inputting the wrong value into ION. We made buttons and interactions on Runs 2.0 much larger to assist.
* Action Bar: The action bar now reacts to the state of the step at any given time. For example, if the step is in TODO, you will see a Start button which will bring the step in progress and check you in automatically. We utilized this opportunity to eliminate the confusion of beginning a step and checking in. There is always an overflow menu that allows you to perform less frequent actions.<br>

  <figure><img src="/files/jvcdAIWk5RnzlkQOTbCO" alt=""><figcaption><p>Start and Check In are Combined when Step is in TODO</p></figcaption></figure>
* Check In Status Bar: Now at all times if you are checked into any run step from the color of the top bar in ION. If it's green, you have an estimated labor time remaining on that run step. If's orange, you are out of estimated labor time on that run step. In addition, there is a new pop up that shows you all steps you have checked into for easy check out and navigation purposes.

  <figure><img src="/files/wnY8KY1Mrn5RS8PLvJal" alt=""><figcaption><p>The Top Bar is Orange Because you are past the expected labor time</p></figcaption></figure>

  <figure><img src="/files/iO8jmrNKq1yLGY6nqi7C" alt="" width="375"><figcaption><p>Check Out Pop Up</p></figcaption></figure>
* Run Execution and Run Summary are combined: Frustrated with having to navigate to the run summary to change the location or assignee of a run step, view kits, see redline history and merge, etc.? This is now all accessible directly at the top of the run execution screen. It is hidden by default, but can be accessible by clicking the expand button!
* Expanded Issue Creation: The issue creation pop-up now allows you to assign users and add information for all of the attributes your organization has configured for issues. Combined with [ION actions](/features/ion-actions), you can now ensure that information is captured on every issue.

  <figure><img src="/files/txp1c7gLDCQQwGI3rMd4" alt=""><figcaption><p>Issue Creation in Beta</p></figcaption></figure>

  <figure><img src="/files/y1XySJOlT2s7PuxcglYh" alt=""><figcaption><p>Attributes can be Populated on Issue Creation</p></figcaption></figure>
* Digital Run Step QR Code: You can use the digital QR code on every run step to quickly send the URL to multiple team members or have a team of technicians quickly scan the barcode to check in on their mobile device to ensure accurate labor hours or an inspector can scan the barcode to signoff on a quality inspection on their mobile device instead of carrying around a laptop or tablet. You will need to login on your phone just as you would on any device.

<figure><img src="/files/zVSbAglC6gpvV1nwEOaQ" alt="" width="375"><figcaption><p>Digital Run Step QR Code</p></figcaption></figure>

<figure><img src="/files/JKnpLoPo81kJC8fHUAJj" alt="" width="375"><figcaption><p>Mobile Check in via Web Browser</p></figcaption></figure>

<figure><img src="/files/KcTldAuYGu5XNakAFs1s" alt="" width="375"><figcaption><p>Quickly Sign off on Fields on Run Steps</p></figcaption></figure>

1. [Redlines](/features/runs/redlining)
2. [aBOM Beta Changes](/features/parts-and-trace/trace-aboms/abom-beta-changes)
3. [Batching Runs](/features/runs/run-batches)


# Runs And Step States

States step

## Run Step Status

Steps on runs are like a checklist indicating what work was done and how. Each step in a run has a unique state. That state indicates the status of the work called out in the step's work instructions. Below are all of the states of a Run Step and the different states they can transition to.

<figure><img src="/files/LsP63eSZCXsbiGk1bikS" alt="" width="563"><figcaption><p>Run Step States</p></figcaption></figure>

### Available to Work

Available to Work is a separately calculated attribute that ION uses to help indicate to users whether or not a run step can be worked on. It's calculated by taking into account the following:

* Are all upstream dependent run steps **Completed**?
* If a parent step exists, then is it **In Progress**?
* Is the current step in **Todo** or **In Progress?**
* ***Future State:*** Are all blocking issues resolved?

If all of the conditions are met then the step is considered Available to Work.

## Run Status

{% hint style="info" %}
The run calculates its status based on the status of its steps. This gives teams a high level overview of the state of the run! Below are the states of a run.
{% endhint %}

### Todo

This is the initial status for steps when they are created. A step in **Todo** means no work has been done against that step.

A run with steps all in **Todo** will also show the state as **Todo**

### In Progress

A step **In Progress** has been started by a user. Steps can only be moved from **Todo** to **In Progress** if all their upstream dependencies have been moved to the **Complete** state. Transitioning a step from In Progress to any of the other states as seen below will automatically check out all users who are currently checked into that run step.

![The ION UI will block you from starting a step until its upstream dependencies are complete.](/files/EWOe36VaYNyWuqaxHFJW)

### Completed

A **Completed** step has had all its required fields filled out and all its work completed.

Runs with all steps **Completed** will also be **Complete**

### Hold

**Hold** is a special administrative state used to prevent steps from being executed. This could be used to block work from being done or to pause an operation while an issue is being investigated.

A run with at least one step in **Hold** status will also inherit the **Hold** status.

{% hint style="info" %}
Steps in **Hold** state are called out in yellow.
{% endhint %}

### Redline

**Redline** steps are in an editable state and cannot be executed. See the [**Redlines**](/features/runs/redlining) page for more information.

A run with at least one step in **Redline** status will also inherit the **Redline** status, and the Redline status takes precedence over the Hold status.

{% hint style="info" %}
Steps in **Redline** state are called out in light red.
{% endhint %}

### Failed

**Failed** steps indicate something went wrong. This could be a part or process was found to be non-conforming or an inspection was failed. You can trigger this step by clicking the **Fail Step** button in execution mode after this step has been started.

A run with at least one step in **Failed** status will also inherit the **Failed** status.

{% hint style="info" %}
**Failed** steps are colored dark red.
{% endhint %}

If set up in your organization settings, a Failed step will automatically trigger the creation of an issue ticket. From here, you can insert your cause, expected condition, and disposition.

You are able to freely change a runstep from Failed status to `Todo` or `Redline`.

### Canceled

If a user with appropriate privileges decides that a step can be skipped, they can cancel the step. Canceled steps can be moved back to **Todo** to be un-canceled.

If every step in a run is canceled, it will calculate its status as **Canceled.** If the run is comprised of a mix of **Complete** and **Canceled** steps, it will use the status **Partial Complete** to indicate no more work can be performed but not all the work was done. Otherwise, the run will use the other rules from the above states to calculate its status.

{% hint style="info" %}
**Canceled** steps are displayed in dark gray
{% endhint %}

#### Canceled Steps Dependency

{% hint style="info" %}
Contact your Customer Success Manager to opt out of non-blocking canceled steps.
{% endhint %}

Run steps can have dependencies on other run steps which prevent them from being worked on. Consider the dependency graph below, Step 4 `Assemble tail` has two dependencies - `Step m1` and `Step m2`. Only `Step m1` is blocking since `Step m2` is complete.

<figure><img src="/files/8buYY7YH4FpW4IjxxpXP" alt=""><figcaption></figcaption></figure>

If we cancel a `Step m1`, we have decided it can be skipped and it should no longer block other steps, so it is removed from the dependency graph. The dependency graph is rewired to ensure its dependencies remain in tact. `Step h1` which was blocking `Step m1` is now blocking step `Assemble Tail` as seen below. `Assemble Tail` can now be worked since all of its dependencies have been completed. This feature prevents canceled steps from blocking downstream steps while the dependency graph makes sure work gets done in the correct order.

<figure><img src="/files/rvAEsGB7r75lVKtFcmSs" alt=""><figcaption></figcaption></figure>

In batched runs, each run will receive this behavior when canceling a step. Each corresponding step will be removed from the dependency graph and each dependency graph will be rewired to ensure dependencies remain in tact.


# Batching Runs

How to leverage batching to supercharge your manufacturing.

## Run batches

When working with many parts at once it can get repetitive to manually input information for runs that go through the same operation. The **Batch** function groups into batches where updates to the runs are synchronized to save time.

{% hint style="info" %}
Any set of runs can batched together, regardless of what steps they contain
{% endhint %}

Run batches work by propagating changes made to one run to the others it is batched with. It doesn't matter which run you make changes to. The run's assigned user, due date and step progress will be synchronized.

ION will intelligently pick steps to synchronize based on step data - see the full list of rules below in [#batch-propagation](#batch-propagation "mention"). This allows runs to be batched together even if they go through different processes in the past or future.

## Creating a batch

Runs can be added to batches during creation using the "batch runs" checkbox, any time after creation using the **Batch** column in the runs table view, or in a run and selecting the batch button as seen below.

{% hint style="info" %}
A run can only be in one batch at a time, but you can remove a run from a batch and add it to another at any time.
{% endhint %}

* During the Run Creation Process

<figure><img src="/files/jHv7dnPriqv5YwyTrXh4" alt="" width="563"><figcaption><p>Batching runs during run creation</p></figcaption></figure>

* From the Runs Table view

![Run batch status in runs table](/files/tsIqjkJLBgYYcdRsllG3)

* Within the Run itself from the run header

<figure><img src="/files/RyFaqQZzQIhLp4tSnmp9" alt="" width="405"><figcaption><p>Hit the Create batch button to pull up the below model</p></figcaption></figure>

<figure><img src="/files/8BbZbKSLkXhYI4TSHROK" alt="" width="563"><figcaption><p>Add this run to an existing batch or to a new batch!</p></figcaption></figure>

## Viewing a Batch

Runs in a batch display a batch information banner at the top of the run header which can be clicked on to see information at a glance and then expanded to have more control over the batch.

<figure><img src="/files/XVW7imztyYa5U8zv4a5V" alt="" width="563"><figcaption><p>Run execution highlights runs affected and total runs in batch</p></figcaption></figure>

<figure><img src="/files/PLPDhMqKzxSBU4arBhiR" alt="" width="473"><figcaption><p>Batch information at a glance from clicking on the batch</p></figcaption></figure>

When looking at the batch overview, clicking a different run will navigate you to that run.

<figure><img src="/files/yPP1EH7y8qADJ5GcHCE5" alt="" width="563"><figcaption><p>Detailed batch view by clicking on the blue arrow next to the batch details</p></figcaption></figure>

## Batch Propagation

## 🧩 1. **Batch Matching Logic: Structural Identity** <a href="#id-2f2cd8ab-9949-48b8-836a-42ff340e2346" id="id-2f2cd8ab-9949-48b8-836a-42ff340e2346"></a>

***Behavior***

Batchable steps are determined by **system-defined identities**:

* **Last redline is the same**
* **Standard Step ID** is identical (for standard steps)
* Or, the **origin step ID** is the same (for procedure steps)
* **Step must be in TODO status**

***What this means:***

Rely on core structural traits to better identify batchable steps.

***

## 🔄 2. **Batching Impacts Nested Steps and Enforces Parent-Child Hierarchy Matching** <a href="#id-0927e26f-ab29-4c4f-9b01-5b2e4bf705c3" id="id-0927e26f-ab29-4c4f-9b01-5b2e4bf705c3"></a>

***Behavior:***

* The **entire step hierarchy**—including **nested steps**—must match for batching to occur.
* Nested steps to a depth of more than 1 will now also batch.

***Impact:***

This prevents partially batched workflows due to hidden structural differences and reinforces step-by-step alignment across runs.

***

## 📤 3. **Data Shared Across Batches** <a href="#id-7e3c08e3-0dc9-48f2-ade7-120497c3cd6a" id="id-7e3c08e3-0dc9-48f2-ade7-120497c3cd6a"></a>

**More consistent batch-shared data:**

* **Redlines to existing steps**
* **Adding new steps**
* **Dependencies**
* **Check-in session data**
* **Status**
* **Scheduled start**
* **Scheduled end**
* **Assigned user**
* **Lead time**
* **Workcenter**
* **Field entries**
* **Datagrid entries**
* **Comments**
* **File Attachments**

***Takeaway:***

The system now treats batches more like a **living procedural container**—including structural changes (like added steps or redlines), not just step updates. This means changes ripple through the batch more comprehensively.

***

## 🚧 4. **Rules on Step Status and Batching** <a href="#id-5daa172b-221a-4291-b537-976960b1d27f" id="id-5daa172b-221a-4291-b537-976960b1d27f"></a>

***Behavior:***

* You **cannot un-batch** a run if any of its steps are in a **REDLINE** status.
* Only steps in **TODO** status are eligible for batching.
* To reapply changes to completed steps via batching, users must **reset to TODO**, batch, then reapply changes.

***Why this matters:***

This protects data integrity by ensuring batches reflect only modifiable, aligned steps—and keeps post-execution changes deliberate and controlled.

***

## 🔗 5. **Enforcement of Dependency Logic in Batches** <a href="#id-2f344bb5-19d4-4a5b-8fec-0e70d857d120" id="id-2f344bb5-19d4-4a5b-8fec-0e70d857d120"></a>

Clear rule: **A downstream step in any run can only begin when the equivalent upstream steps in ALL batched runs are complete.**

<figure><img src="/files/IlQwbo2V5K0JtgqB1qGn" alt="" width="563"><figcaption></figcaption></figure>

***Consequence:***

As you may change one run that had an issue to ensure it got repaired before rejoining a batch, this ensures **those repairs are completed in advance of that part rejoining the batch, as an example.**

***

## Completing a Batch

You can move all completed inventory within a batch when a batch is completed.

<figure><img src="/files/idgestjOLcH07kAQjvdi" alt=""><figcaption></figcaption></figure>

## Adding and removing individual runs

If the data/process of a particular run have a need to diverge from other runs in the batch, the run can be removed from the batch and modified independently. Similarly, other runs can be added after batch creation too.

Click on the batch label and use the batch edit sidebar to add and remove individual runs.


# Workcenter execution

A view focused around a single workcenter to streamline medium and high-volume work

## Overview

Navigate to `Workcenter execution` from either the runs menu or from the location view. Select a workcenter and see all open steps (todo or in progress) in the left side panel.

Completing steps will automatically open the next step in the queue, allowing you to process work quickly within your workcenter.

**Note:** *many links on this Beta release will point back to the current runs view. This will change over time as we continue to add content to this view*.

<figure><img src="/files/yyQGPJmoStsZcYKMp0Dm" alt=""><figcaption></figcaption></figure>

## Top bar

The top bar is part of our new design system which has some high level information such as notifications, some navigation, and a color scheme that is inspired by [Andon lights](https://en.wikipedia.org/wiki/Andon_\(manufacturing\)).

When you check into any step, the top bar will turn a different color. If the total duration worked is less than the leadtime of the step, the color will be green. Otherwise, the color will turn orange.

Within the top bar, the steps checked in by you will be shown with navigation to easily check out of the step.

<figure><img src="/files/tXaETDLbd39ElkG0ne36" alt=""><figcaption></figcaption></figure>

## Step queue (left side panel)

The left side panel shows a queue of steps that can be sorted by a number of different options. This panel can be collapsed as desired. Only steps that are in progress or todo will be shown here.

## Content (center)

The center of the screen features 3 sections:

* **Step header**: shows information about the step with links to the run
* **Inventory card**: if an inventory is linked to the run, it will display here. Use the links to go to the part library or the inventory.
* **Work instructions**: shows the work instruction content

<figure><img src="/files/czQZ4HL7wT7BVF7wRlxO" alt=""><figcaption></figcaption></figure>

## Right side panel

This section mirrors what is currently shown on run execution. There is one addition here with **parts** that will show which parts are required to be installed at this step. This is largely a placeholder at the moment and will have much more functionality in the near future.

## Action bar (bottom/footer)

* **Create issue**: quickly create new issues
* **Action buttons**: take action to start, check-in/out, complete, and fail steps from the bottom bar
* **Deliver to**: displays a location for where the following step in the run takes place based on defined dependencies.


# Split Inventory on a Run

Discover the functionality of splitting WIP through an issue ticket. This helps with splitting inventory on a run when an issue with some parts is detected.

### **Use Case:**

During the receiving process, you're looking at 10 parts provided by a supplier. After conducting an inspection, you note that 3 of those 10 parts contain visual defects that deviate from the expected condition.

**How do you address the issue with those 3 parts without holding up the progression of the other 7 through your process?**

In ION you can create an issue ticket to handle just those three parts, assign a location to them such as an MRB cage, and continue running the remaining seven.

[For information specific to issues check out this page with more details.](/features/quality/issues)

The video bellow shows you how to execute this functionality in the run execution window.

{% embed url="<https://www.loom.com/share/faff54d6358440b7ab0b498b996e24d5?sid=ce15a86d-0a36-442f-ac83-fb2f676f005a>" %}
Lot Tracked Split WIP Functionality
{% endembed %}

### **Case Study:** Create 5 "New York Cheesecakes" and Split Off 2 Mid-Process

This is a more complicated case were the parent inventory item has multiple child components required to build it, these are the aBOM build requirements.

{% embed url="<https://www.loom.com/share/b6eba281f3024ccca9c6a4c98298349c?sid=f5321420-5dd3-4a46-8759-f158e2f5359d>" %}
How ION handles splitting build requirements on a split WIP assembly
{% endembed %}

**Steps followed in the video:**

1. Establish the run to produce those five cheesecakes.
2. Once the run has been created you will see these in inventory as WIP. They will also be assigned a location of your choosing, in this case the "Great Place".
3. The build requirements (aBOM) for a singular cheese cake is setup to be 3 Sugar, 2 Cream Cheese, and 1 Egg. This will be important when we create an split WIP issue with partially installed quantities.
4. Total Build requirements for the five cheesecakes is thus: 10 cream cheese, 15 sugar, 5 eggs.
5. During the procedure you have installed 2 sugar and 1 cream cheese when you notice there is an issue with two of the cheesecakes. The location of the installed goods at this point is in the "Great Place" where the cheesecakes were originally destined for.
6. You create an issue ticket to split those two cheesecakes off the run and put them in a location called "Bad Place".
7. From the inventory page page, you will now see that those two split cheesecakes are available now in the "Bad Place". If "Bad Place" was an "Unavailable" inventory location, users could use it as a way to make split-off inventory "Unavailable" for use elsewhere.
8. Likewise the current logic is that all components installed into the split-off inventory will also move to the new location "Bad Place".
9. Looking at the aBOM now for this run you will see a couple additional pieces of information.
   1. For build requirements that had some inventory installed before the split, they will now show a UI indication that they are shared between the two parent part inventories. In the video's example, it shows the build requirement is linked to inventory ID 12 and 15.
   2. The quantity looks like Qty: 1 of 6 (10). Hovering on the tool tip shows you that 1 inventory is still installed on the build requirement, quantity 6 is the current quantity required by the build requirement of the part, and quantity 10 was the original build requirement quantity. Since it's impossible to exactly know whether the qty 1 was a component of the newly-split off inventory or still in inventory attached to the Run, the previously installed inventory will remain visible on the Run's aBOM even after the split.
   3. 6 total sugar are needed for the remaining three cheesecakes down from original 10 demanded.

### Logic Diagrams:

Imagine you’re overseeing a production process where items (like machines or baked goods) are built from several parts or materials. In some cases, problems come up, so you need to separate out certain items from the production line, while still keeping track of what’s been done. These scenarios explain how the system manages and tracks parts, depending on how far along they were in the assembly process.

These diagrams show how inventory will be divided up based on full installs, partial installs, or no aBOM install scenarios. The final locations of children inventory will be reflective of the locations of the child parts (pink boxes) after the split (on the right side of the arrow).

#### Scenario 1: No Parts or Materials Installed Yet

In this scenario, nothing has been added to the items being produced yet—no materials or components are installed. Let’s say you need to separate out a few of these items before any work has begun.

* **Outcome**: When you split off some items, the system divides all the necessary parts and materials between the two groups without confusion. Each split-off group will have its own list of parts to be installed, and since no materials were installed beforehand, each group’s requirements are completely independent.

This scenario is straightforward because there are no partially completed items to complicate things.

<figure><img src="/files/VrBdhd95QquDTQyucSQG" alt=""><figcaption><p>Splitting a parent part that has has no installs against it</p></figcaption></figure>

#### Scenario 2: Some or All Parts or Materials Installed

Now, let’s say work has already started, and some of the materials or parts have been installed. You then realize there’s an issue with a few items and need to separate them. The problem here is that some materials have already been used, so it’s not clear which parts belong to which group.

* **Outcome**: The system links both sets of items (the ones you’re keeping in production and the ones you’re separating) to the already installed parts. This way, each group will show the installed parts as “shared” between them, meaning the materials could belong to either set.

This approach makes sure no materials go unaccounted for and that both groups have the components they need because it is unclear exactly which group each part should belong to after the split.

<figure><img src="/files/zBODayA5orshkuUTm60x" alt=""><figcaption><p>Splitting a parent that has requirements fully installed or partially installed</p></figcaption></figure>

#### Scenario 3: Mix of Installed and Uninstalled Parts

In this case, some parts or materials are installed, but others haven’t been added yet. Let’s say half the materials for each item are installed, while the rest are still waiting to be added. You then need to split out a few items due to an issue.

* **Outcome**: The installed materials will be handled as in Scenario 2, linked to both groups, meaning the system shows them as “shared” between the items in production and those being set aside. Meanwhile, the materials that haven’t been installed yet get allocated separately to each group based on the split.

This setup keeps things organized by showing which materials are completely ready and which are still needed. It allows production to continue for the items that aren’t affected while making sure that the separated items are accounted for accurately.

<figure><img src="/files/Q3tAzIMQlm6iBLKh33dW" alt=""><figcaption><p>Splitting a parent that has some requirements fully installed and other requirements with no installs</p></figcaption></figure>

### aBOM Installation Sharing amongst Parent Assemblies

As mentioned above, when parent assemblies are split, we make no assumptions as to where the installations should belong because we cannot confidently understand which parent they belong to. If you install multiple lots as an example, how do we know which lot belongs to which parent assembly? As a result, the aBOM installations are shared amongst multiple parent assemblies. To simplify your accounting needs when this occurs, we created a table below to help you calculate how much quantity and cost can be attributed to one aBOM.

<figure><img src="/files/AI1NOSwYrjK3MRSZvgJV" alt=""><figcaption></figcaption></figure>

#### Uninstalling a shared installation

Because a shared aBOM installation is a single record linked to every lot produced by the split, **uninstalling it removes it from all of those lots — not only the one you are viewing.** This is propagation across the shared lots, not a loss of historical traceability.

ION makes the shared relationship visible so the change is deliberate:

* Shared build requirements show a **Shared with N lots** indicator.
* When you uninstall, ION lists the affected lots, grouped as **Direct siblings** (lots from the same split) and **Other related lots**, and asks you to confirm.
* When you uninstall, the removal is held for about 10 seconds — a countdown lets you **Cancel** before it applies. If you don't cancel within that window, the part is removed from every lot that shares it.

Installing into a shared requirement, or editing its quantity, is also reflected on all of the sharing lots; only uninstall asks for confirmation first, since it is the change most likely to affect a sibling lot unintentionally.


# Redlines

In a fast-paced manufacturing environment, work instructions and test procedures will need to be updated to handle changing engineering requirements, and non-conformances, or to simply create faster and higher quality processes. Redlines allow Runs to be edited with full traceability and sign-off processes. Many times, redlines are even used to build out entire procedures in a build-as-you-fly manner.

{% hint style="info" %}
Users must have a role with the *createRedline* and *updateRedline* to redline a run!
{% endhint %}

## Starting a redline

Click the three dots indicator on the action bar to redline an existing step. Alternatively, use the redlines button in the run header to select a position where a new step can be added.

<figure><img src="/files/SGEZgfCARIfmQFR31EF7" alt="" width="532"><figcaption><p>Redline existing step</p></figcaption></figure>

<figure><img src="/files/RMEktFwEvbK8gbn6b9Bz" alt="" width="393"><figcaption><p>Add a new step via redline, or view previous redlines</p></figcaption></figure>

When adding a new step via redline, you can choose to link it directly to an issue. The issue persists when clicking ***Save and Add Another Step***, allowing you to create a series of redlines related to an issue in quick succession. You can then find a step to add via the search and filters to narrow results to find the exact step you care about. For example, you can create a standard rework procedure that you can pull steps from in rapid succession to create many redlined steps that then get approved all at once using the [new approval process](#approving-redline-changes).

<figure><img src="/files/ApOqVeUbazmfbrPbWyN5" alt="" width="477"><figcaption><p>Filter a step you are adding via Redline via many options and add the redline directly to an issue when creating it</p></figcaption></figure>

If you choose not to select a step from the results menu, a new step will be created with the selected step type. As mentioned above, you can create entire runs from scratch without needing a procedure in a Build-as-You-Fly manner. These can then be saved back to a procedure later via the [merging process.](#merging-redlines-to-a-procedure-or-to-a-run)

In addition, you can select the precise position of the step to be added. If not selected, the step will be added to the end of the run.

<figure><img src="/files/Iy1XEglLneHNmaHVNU2i" alt="" width="484"><figcaption><p>Adding a new step details</p></figcaption></figure>

## Editing a step in redline

Steps in redlined states are indicated with a warning at the top of the step and a red pencil icon on the step queue on the left. When a step is in the redline state, the step content, fields, datagrid rows/columns, and values all may be edited, added, duplicated, or removed. Redline steps cannot be completed or failed. The redline may be canceled at any time to return the step to it's previous actionable condition.

<figure><img src="/files/zr1EmUTQUEbm2dCW9NTX" alt=""><figcaption><p>Warning and indicator that a step is in redline</p></figcaption></figure>

<figure><img src="/files/SqJLWBF4AsumZPV0z9iZ" alt="" width="293"><figcaption><p>Duplicate a field</p></figcaption></figure>

If a step is in redline, the dependencies attached to the step can be deleted. Both steps need to be in redline to add a dependency between them.

![Redlined steps are shown in red and editable dependencies are shown with red dotted outlines](/files/cHe1iBuWzgqmwZ4bZL4z)

## Redlining a standard step

Redlining a standard step works the same as redlining a step. Click the ellipsis next to the step title and click "Redline Step"

<figure><img src="/files/GJJQwqd7ftVkiVuq2zJx" alt=""><figcaption><p>Putting a standard step into redline</p></figcaption></figure>

## Approving redline changes

Add reviewers through the multi-select user dropdown on the *Review Redlines* screen, and then add them as reviewers to the appropriate redlines.

<figure><img src="/files/szOMHF81mOwMu8ydbMUJ" alt="" width="563"><figcaption><p>Add reviewers in bulk</p></figcaption></figure>

<figure><img src="/files/QhlEVGL6HxGZ6WML1Exx" alt="" width="563"><figcaption><p>Select redlines per reviewer to approve</p></figcaption></figure>

If you have been assigned as a reviewer, run steps that are in redline show up in the run header and can be viewed and approved in the *Review Redlines* pop up. In addition, check the *Review Center* in the top right next to your avatar to see all redlines waiting your approval.

<figure><img src="/files/wF4hm7m2xPXYfEyODcl4" alt="" width="269"><figcaption><p>Notification icon next to your avatar takes you to the <em>review center</em></p></figcaption></figure>

Each redline in the *Review Redlines* and *Review Center* will give you a live diff of the changes made to the redline as seen below, making it simpler to approve changes by just clicking "Expand Diff"!

<figure><img src="/files/zd7EBm6a6j8U0zEWSMnl" alt="" width="563"><figcaption><p>Live Diff of changes made during the redline process</p></figcaption></figure>

Once you have reviewed all of the redline updates, you can approve them, reject them, or simply add feedback for the original editor to use to update the redlines further.

1. When assigned as a reviewer for multiple redlines, you may approve an individual redline on a run step or approve all redlines assigned to you to review in a single run. For example, if you are set to review five redlines in a run, you have the opportunity to review and approve them all at once at the bottom of the *Review Redlines* screen. We know our customers often create a sequence of redlines that are connected, and should be reviewed together before being approved collectively via this screen!<br>

   <figure><img src="/files/z7aUzc6XoBLunrE1sWcI" alt="" width="563"><figcaption><p>Redline reviews allow you to review and approve many redlines on a single run at once</p></figcaption></figure>
2. After you've approved your redlines, you will need to submit them. A redline can be submitted on the steps using the submit button below.

<figure><img src="/files/CPRsSu0Am5rNqHduR9TI" alt=""><figcaption><p>Submit button for Redlines</p></figcaption></figure>

3. If you'd like to have redlines always automatically submitted, there is a check-box on your organizational settings like in the photo below:

<figure><img src="/files/gTbFMWcyrT6X7plagBgY" alt=""><figcaption></figcaption></figure>

3. If you have been assigned as a reviewer for [merged redlines](#merging-redlines-to-a-procedure-or-to-a-run), approve all of the run steps that have merged redlines at once from the *Review Center*. This is for when you have merged a redline to dozens of other runs to ensure all of the changes get propagated to similar runs.<br>

   <figure><img src="/files/mUJIz8bNGmrYdTsn5upl" alt="" width="563"><figcaption><p><em>Review Center</em> where you can see redline merges and redlines assigned to you to review</p></figcaption></figure>

See all of the comments and feedback for a given redline from the *History and Merge* screen. This screen shows all completed redlines and their complete history of changes and feedback that have been made to the step via the redline process as seen below.

<figure><img src="/files/ladFEGIwypeuA402YCJE" alt="" width="484"><figcaption></figcaption></figure>

## Merging Redlines to a Procedure or to a Run

If you make a redline improvement to work instructions on a run, merging allows those improvements to be duplicated quickly into other similar runs and procedures. Imagine having 20 other runs that utilize the same set of instructions, merging allows you to bring them all up to date in one push. Run Steps and Procedure Steps you choose to merge to will automatically update to be identical to the source step when accepting the merge.

1. A redline must be submitted before it can be merged from the redline *History and Merge* screen.

<figure><img src="/files/Ykr1nNrFYuV24YcisHhp" alt="" width="563"><figcaption><p>Merge submitted Redlines to other run steps or procedure steps</p></figcaption></figure>

2. Here you have multiple options to merge. If you chose to merge to a procedure, you have the option to merge to an existing step or merge to a new step at the end of procedure. If the procedure is not in a draft state, than a draft of that procedure will automatically be creating when merging to any step in that procedure.<br>

<figure><img src="/files/jnxDMlfv8sN6OP0vNjAW" alt="" width="563"><figcaption></figcaption></figure>

<figure><img src="/files/di5YpO74cvFUnwL7ySb5" alt="" width="563"><figcaption><p>Warning when merging to a released procedure</p></figcaption></figure>

{% hint style="info" %}
If the procedure chosen is not in draft, the merge feature will automatically create a new draft version to merge into.
{% endhint %}

3. When merging to a run, you can select many different runs and steps to merge to. Before merging, you will have the opportunity to assign a reviewer to the merge which will allow that reviewer to approve all of the merges at once instead of approving each merged redline independently. Once the merge is complete, each destination run step will be placed in redline and mirror the source step. As with any redline, you will still have to approve and submit them, so we recommend selecting a reviewer before merging in order to have the option to approve them all at once as seen in the [approval section](#approving-redline-changes) above.<br>

<figure><img src="/files/M8Thbjn9SzvYp7mjxDEN" alt="" width="563"><figcaption><p>Select an approve before merging</p></figcaption></figure>


# Export run data

Run data can be exported from the Run summary

## Exporting CSV and all assets

You can export run data from an individual run using the "Export" dropdown menu in the Run Summary for a given run. You'll be sent an email with a zip file containing the export. Run Only exports information directly pertaining to the run. Run w/ Assets exports Run Only information and any attachments associated with it.

![Export Button for Runs](/files/S9MGTtWjlxHUKzW2yEd8)


# Scheduling runs

How to schedule runs in ion and view your factory schedule

### Scheduling and assigning a run

Runs have multiple steps. Each step is can be unique and will have their own lead time and schedule. In the summary view for a run (Runs -> Click on a run), you can schedule each step's start and end schedule, along with a lead time.

<figure><img src="/files/mKx77e6C2rhhVl4BAebN" alt=""><figcaption><p>Scheduling both an individual step, along with the entire run</p></figcaption></figure>

{% hint style="info" %}
If the run start time and end time are not set but individual steps in the run have start and end times set, the run will automatically set its start and end times to the earliest start and the latest end.
{% endhint %}

### Viewing production schedule

From the main **Runs** view, click on the Timeline button on the top. Here, you can see all of the runs scheduled in your factory in a Timeline. Below the chart, you can see unscheduled runs.

![](/files/sStjMewziChA4n6ZAGgt)

Clicking one of the items in the left column will pop out the right side and allow you to schedule the run. The timeline window will reflect your changes automatically.

![](/files/2wfj8Zaji956XpAeXHIG)


# Time Tracking

ION automatically tracks the time users spend executing steps in runs to give teams an accurate representation of how much labor time was spent on each operation. In turn, that data can be used in our [Analytics](/ion-analytics#standard-dashboards) tool to help you determine cost estimates per assembly! To track time, an operator has to check in to start the capture of time and check out when they are finished working. Each check-in and check-out pair is **called a session** which can be edited as seen below.

Our goal is to make this as seamless as possible to ensure the least overhead for operators when performing work so that they spend most of their energy working while having confidence that ION is tracking their work accurately. To do this, we have a few automations and validations that are online and a few more we are considering:

* When an operator first begins a step (step moves from `TODO` to `In Progress`) they are automatically checked into that step.
* When an operator `Completes` a step, places a step on `Hold`, places a step in `Redline`, or `Fails` a step they are automatically clocked out.
* Operators are prevented from being checked into a run step when the step is not `Available to Work`*.* `Available to Work` implies a run step is in `TODO` or `In Progress`, is not blocked by upstream run steps, and the parent step, if exists, is `In Progress`.
* **Future State:** When an operator checks in while the run step is `Available to Work` and in the `TODO` status, the run step will be automatically moved to `In Progress`*.*
* **Future State:** When editing any data in a run step while the run step is `Available to Work` and in the `TODO` status will automatically move the step to `In Progress` and check in the current operator.

#### Understanding and Updating Existing Session Data

If you want to understand how long you've been checked into a step, the total duration of check-in time per step or want to edit the time someone has been checked into a step, click on the gray checkmark in run execution mode as seen in the video below. If you have the permission to `UpdateSession`, then you can also edit the check-in time and the check-out time.

{% embed url="<https://www.loom.com/share/6df924d8765f4fd29db2168d76f1f226>" %}

An alternative method to update session durations is directly through the API. For step-by-step instructions, please visit the [API > Examples > Edit Time-Tracking Session Data](/api/examples/edit-time-tracking-session-data) page within our manual.

The *Currently Clocked Into* widget on the home screen shows what steps you're clocked into and the status bar at the top informs you of all steps you are checked into.

Users who are checked in are highlighted green and have a green checkmark next to their avatar and will appear on the step queue on the left.

<figure><img src="/files/mzpi8C3wfjqsoM73W3Lv" alt=""><figcaption></figcaption></figure>

### Using a smart card badge for login authentication

Badge authentication can make it easy for multiple users to login via their badge and check into operations, buyoff steps, etc. Below is an example of badge authentication to Windows 10 hosts that has been successful by using the following technologies:

* Smart card: Taglio PIVKey C910
* Smart card reader: HID Omnikey 5422
* Smart card certificate: Smart Card Logon

1. Configure a Smart Card Logon certificate template on internal Windows Certificate Authority ADCS.
2. Explicitly grant a predefined security group access to read/enroll via the template’s permissions.
3. Write a PowerShell script to simplify the process of requesting a certificate (certreq), setting a pin on the badge PivKeyTool), and writing the certificate to the badge (certutil).
4. After the PowerShell script completes successfully, the badge can then be used to login to a Windows 10 device.
5. The user must insert/touch their badge to the reader, and input their pin.
6. We’ve seen a successful authentication rollup from the OS to the browser (Chrome/Edge), which automatically authenticates the user to Azure AD. This helps the workflow immensely, as they can easily reach First Resonance ION soon after login.

Some improvements during your implementation may consider making the certificate request process easier, as well as implementing automated smart card certificate revocation on our CA to avoid users having multiple certificates on multiple badges.


# Attributes

Runs support [**Custom Attributes**](/features/custom-attributes) that can be used to add user-defined data fields. Run custom attributes can be set while creating a run and changed at any time through the **Run Summary** view.

![Define run attributes during run creation](/files/aeY14BoeismCIlwcCPtA)

![Run attributes can be viewed and adjusted in Run Summary](/files/Ia08nig6WShlWySKpSg4)

{% hint style="info" %}
Run custom attributes can be edited at any time
{% endhint %}


# Outside Processing

For more information see [Outside Processing](/features/purchasing/outside-processing)


# Runs Best Practices

## **Structured Approach to Placing Procedure Steps on HOLD**

#### Objective

Provide a standardized method for placing procedural steps on HOLD within ION while maintaining contextual visibility and operational transparency.

#### Strategic Rationale

* Enables frontline teams to clearly communicate blockers or required interventions
* Improves visibility of process interruptions across departments
* Supports compliance and continuous improvement workflows

#### Recommended Workflow

1. **Initiate HOLD Action**

   * Navigate to the target step within the procedure
   * Use the dropdown control to place the step on HOLD

   <figure><img src="/files/LNCDB7DmK3OT34enkywE" alt="" width="563"><figcaption></figcaption></figure>
2. **Document the Rationale via Comment**

   * Add a comment to clearly communicate the reason for the HOLD
   * Example: "Step placed on hold due to lack of material availability"

   <figure><img src="/files/6bYNfvxdk0C4DDXXYv6n" alt="" width="563"><figcaption></figcaption></figure>
3. **Alternative HOLD Scenarios**
   * Training in progress: defer execution until personnel are qualified
   * Pending redline or procedural update
   * Identified improvement opportunity under evaluation
4. **Confirm Comment Visibility**

   * Verify the comment is attached to the step and visible in the step sidebar
   * Ensures others can immediately understand the context of the HOLD

   <figure><img src="/files/ub2NtVh90YfS2tAtHrrc" alt="" width="563"><figcaption></figcaption></figure>
5. **Visual Indicators Across Contexts**
   * There are symbols on step cards for comments on the procedure, step, and redline objects
   * Provides a unified reference point for all exception/ HOLD-related documentation

#### Deployment Recommendation

* Use clear, concise language in comments to eliminate ambiguity
* Periodically audit steps on HOLD to ensure timely resolution or escalation


# Parts Library

ION allows you to keep track of your parts as well as keep track of how and where you use those parts in your manufacturing program.

Part objects in ION represent abstractions that carry information about a particular part, while the physical parts themselves are [part inventory objects](/api/examples/part-inventory-and-kitting#inventory). The part objects dictate the mBOM, revision, supplier part number, tracking type, lead time, unit of measure, and other additional attributes about a part that get carried over to your factory. A part is a unique combination of Part Number and Revision.

## What is a part, and when should I create a Part?

A part represents a unique combination of parts and processes that can exist as a standalone product in your inventory. We recommend creating a part if it meets the following criteria:

* An instance of that part (i.e., part inventory) can be stored in a warehouse.
* An instance of that part can be used interchangeably across any serial number of one assembly or be used in multiple types of assemblies (i.e., different part numbers).

Here are example use cases:

* A part comes in unpainted (i.e., -001) and can be used for R\&D, or can be coated (i.e., -002) and used for flight purposes. This part meets both criteria; it can be stored in a warehouse, and the part can be used for R\&D or Flight if coated. In this case, we do recommend the -002 calls out the -001 in the mBOM.
* A car engine that is stored in inventory and can be used for any sedan serial number that comes down the line.
* Paint that is used for any vehicle, whether it's a sedan or a SUV.

When we DO NOT recommend creating a part:

* If every part always gets painted during the manufacturing process, than we don not recommend a unique part number for the unpainted part. If the unpainted part is ordered from a supplier, we recommend using the [Outside Processing](/features/runs/outside-processing) feature to support this use case!
* You need to break up a large procedure into smaller segments to effectively split up the procedure definition into multiple teams and more manageable chunks. Instead of creating unique part numbers for each procedure to represent each state of the assembly, we recommend using [Procedure Best Practices](/features/procedures/procedure-best-practices#use-case-implementing-nested-steps).

## Design Changes: When to Iterate on Part Numbers, Revisions, and mBOM Versions

There are many ways to iterate on your designs in ION; part number changes, new revisions, or iterating on mBOM versions. This guide is to help propose clarity so you know how to get the most out of the system.

* **Change the Part Number** when the item no longer has the same **form, fit, or function** as its predecessors, and you need to treat it as a different, non-interchangeable thing in planning, purchasing, inventory, or use.
  * *Effect:* New Part Number → starts at a new Revision “A”; has its own mBOM and inventory.
* **Bump the Part Revision** when the item **keeps the same form/fit/function** (policy: interchangeable), but you need a controlled, traceable change (e.g., hole tolerance, finish, spec update).
  * *Effect:* Same Part Number, next Revision (e.g., B → C). Interchangeability can be enforced so you can still kit/install older revs if allowed. Turn on part interchangeability here: [manual.firstresonance.io](https://manual.firstresonance.io/features/parts-and-trace/part-revision-interchangeability)
* **Create a new mBOM Version** when the **assembly definition changes** (components, quantities, substitutes, reference designators) **but the assembly’s Part Number/Revision does not**.
  * *Effect:* Multiple mBOM versions can exist **per Part Revision** with statuses and approvals (Draft → In review → Released → Archived). aBOM/Autoplan use the **latest Released** mBOM version by default. [manual.firstresonance.io](https://manual.firstresonance.io/features/parts-and-trace/manufacturing-bill-of-materials-mbom/mbom-versions)

<table><thead><tr><th width="160.72265625">Change you’re making</th><th>Form / Fit / Function</th><th width="136.5546875">What to update</th><th>Typical examples</th><th>Downstream impact</th></tr></thead><tbody><tr><td>Major change: different form/ fit/function</td><td>Changes</td><td><strong>New Part Number</strong></td><td>New connector type; new envelope size; performance class change</td><td>Separate inventory &#x26; demand; new mBOM lineage</td></tr><tr><td>Controlled design tweak (interchangeable)</td><td>Same</td><td><strong>New Revision</strong></td><td>Tightened tolerance; material callout change; finish spec</td><td>Optionally allow kitting older revs if policy enabled; can auto-flow into mBOMs via automation</td></tr><tr><td>Build definition change only</td><td>Same</td><td><strong>New mBOM Version</strong></td><td>Add/remove child, update qty/substitute, change refdes</td><td>aBOM + Autoplan use latest Released version</td></tr></tbody></table>

### Revisions and Revision Schemas

ION is intentionally flexible when it comes to part revisions, given that every customer has a different schema. In order to set your revision schema, navigate to the parts organization settings and set the format of the revision schema.

<figure><img src="/files/YPJfhJln0DVdguOjL6nk" alt=""><figcaption></figcaption></figure>

You can set the schema to allow overflow, which defines whether an error should be raised when the max iteration of a revision scheme is reached, or if it should overflow to the next available value. For example, you can determine if Z is the last revision in an alphabetical revision schema, or if it should overflow to AA.

The default boolean will automatically mark all newly created parts with this revision scheme unless overriden.

If no revision or revision schema is given, then the part defaults to Rev A. If a revision schema is given, then the part defaults to the first value of that revision schema.

#### Create a New Part Revision <a href="#create-part-revision" id="create-part-revision"></a>

A revision can be generated from any part, there are no restrictions requiring the revision to be generated from the current latest revision. For example if our part "ion-13" has existing revisions A and B, then a third revision C can be generated from either existing revision A or B. [All information in the new revision is copied over from the old revision](/features/custom-attributes) unless explicitly overridden in the mutation input. The new revision will be the next valid alphabetic character from the part's latest revision. If the part's latest revision is C, then the new revision will be D. If the part's latest revision is Z, then the new revision will be AA. Returns the newly created part object with the updated revision.

### Archiving a Part

When archiving a part, ION will prevent any new inventory of that part from being created. Existing inventory will remain unaffected by archiving a part. This will also remove archived parts from dropdowns (i.e. part selection on a run or purchase order). You may unarchive a part by finding them using this filter on the parts library page.

<figure><img src="/files/Zc612lyQBhhHnn5BzXza" alt=""><figcaption></figcaption></figure>


# As-built Bill of Materials (aBOM)

Trace the genealogy of your build in REAL-TIME.

{% embed url="<https://www.loom.com/share/57c6458d50444bceb42c1a69b5b5c3c4?sid=3ab5c0c2-3cc9-4cc7-9078-9c28847a0a2d>" %}

### Overview

IONs aBOM is a powerful tool that allows you to keep track of which parts, down the serial or lot number, were used in higher-level assemblies, across multiple levels of assemblies. The aBOM is a living and real-time document, meaning that changes are reflected instantaneously as parts are installed or uninstalled.

An aBOM is a tree-like scaffolding that connects parent and children inventory. Each node is an inventory item (see: [Inventory](/features/parts-and-trace/inventory)), whether serial-tracked, lot-tracked, or untracked.

The aBOM can be accessed from either runs associated to the assembly, or from the inventory screen as seen below.

<figure><img src="/files/g9W6emqr2UmfLQfy2KrO" alt=""><figcaption></figcaption></figure>

### Why is it valuable

The aBOM is a massively valuable dataset within the factory. The traceability allows for:

* Finding all places that a component is installed if something goes wrong (i.e. containment for recalls)
* Understanding all data that was part of a build: runs, inventory, purchases, etc. This enables aggregations such as understanding the cost of the build or how long it took.

### Getting into the details

The aBOM follows the requirement and fulfillment model like other parts of ION (for instance, kits). Parent inventories have build requirements that define:

* which part is required (including potential substitutes)
* the minimum quantity required
* reference designators (optional)

Inventories get installed into build requirements via aBOM installations. The aBOM installation tracks:

* the inventory installed
* the quantity installed. The exception to this is when the build requirement quantity is set to 0. This allows the operator to install without setting the quantity and just select the trace information such as lot number.
* if it was installed into a specific reference designator

When an inventory is uninstalled, all of its children travel with it. This means that the data for the entire assembly moves with the inventory to match the physical reality.

<figure><img src="/files/4Exm9UKx8dxxIQOLKPu1" alt="" width="476"><figcaption><p>If the Build Requirement quantity is set to 0, a tool tip is displayed informing the operator that the quantity is optional</p></figcaption></figure>

### aBOM construction

You can install into the aBOM as seen in from the run execution screen. From here, you can start adding parts to your aBOM, and even use the "Install from Kit" button to install all the same lot numbers and serial numbers from the kit associated with the run. You can also add parts to the aBOM at the time of execution if needed.

<figure><img src="/files/93AtFOf3YJuaHUD0sEZx" alt=""><figcaption></figcaption></figure>

After installing your parts, the build aBOM changes to Build aBOM (100%) to show that you have installed all of the parts for the run. Build requirements that do not have a quantity greater than 0 do not count towards the final aBOM build percentage.

### Substitutes

On the aBOM, substitutes will appear with the "double arrow" icon shown below.

Here is how they will display within the aBOM interface:

1. The icon indicates that a substitute can be used to fulfill the requirement
2. Expanding the requirement will display the part numbers for the acceptable substitutes
3. When a substitute is installed, the icon will appear next to the installed part

<figure><img src="/files/EcoOFNSjaZWcfJ0ZsPBH" alt=""><figcaption></figcaption></figure>

### Visualizing aBOMs

Even while an aBOM is being constructed, you can visualize the parts that make up the part you are interested in by going to **Parts > Trace.** From here, you can search for a part, which will then load the in-progress or complete aBOM for that specific part. We support a tree view and an indented table view of the aBOM.

![The aBOM maintains a multi-level relationship across BOM items, including serial and lot numbers](/files/ytZUjanY0uXUtkA5OPrz)

<figure><img src="/files/xNYLQa0A8jlbyXigBeEX" alt=""><figcaption><p>The indented aBOM table shows inventory in white rows and build requirements in slate colored rows.</p></figcaption></figure>

### Modifying an aBOM

Simply create a new run for the *top-level assembly that you are affecting*. For example, if you are changing the engine controller on the following BOM:

* Vehicle
  * Engine
    * Engine controller

Create a run with the part number and serial number for the *engine*. Include a procedure with the instructions for changing the engine controller. This will allow the operator to remove the old engine controller and install a new one, by serial (or lot) number. The resulting aBOM will be updated for all levels up the vehicle's aBOM.

#### Permissions

Modifying the requirements of an aBOM has different permissions than installing/uninstalling.

Here is the mapping of permissions to those actions:

* Install a part -> `CreateABomInstallation` permission
* Uninstall/remove a part -> `DeleteABomInstallation` permission
* Update the aBOM requirements (build requirements) -> `Create/Update/DeleteBuildRequirement` permission

<figure><img src="/files/cC3uEoWJGJqv7ataNWgl" alt=""><figcaption></figcaption></figure>

### Uninstalling a part that is shared across lots

The behavior above — where children travel with an inventory on uninstall to match physical reality — describes a part that belongs to a single assembly. There is one case that behaves differently: a part that has become **shared** across multiple lots.

When a lot is split on a run (see [Split Inventory on a Run](/features/runs/split-inventory-on-a-run)), parts that were already installed before the split cannot be confidently assigned to one resulting lot or the other. ION keeps a single aBOM installation record and links it to every resulting lot, so the part shows as installed on all of the lots that share it. This preserves the original traceability without inventing quantities that were never there.

Because that one installation is shared, **uninstalling it removes it from every lot that shares it — not only the lot you are viewing.** The historical genealogy is not lost; rather, the change propagates to the sibling lots. ION flags this before you confirm:

* A **Shared with N lots** indicator appears on the build requirement.
* Before uninstalling, ION lists the lots that would be affected, grouped as **Direct siblings** (lots produced from the same split) and **Other related lots**.
* When you uninstall, the removal is held for about 10 seconds — a countdown lets you **Cancel** before it applies. If you don't cancel within that window, the part is removed from every lot that shares it.

{% hint style="info" %}
Installing into, or editing the quantity of, a shared build requirement is also reflected on every lot that shares it. Only **uninstall** asks you to confirm first, because it is the change most likely to affect a sibling lot you did not mean to touch.
{% endhint %}

Full per-lot divergence of a shared installation is a separate enhancement that is in progress. Until then, sharing is how ION keeps every lot's traceability accurate after a split.

### Sharing Installations Amongst Parent Assemblies

See [Split Inventory on a Run](/features/runs/split-inventory-on-a-run) for more details.


# Editing aBOM build requirements

Edit the requirements of the aBOM called "build requirements"

## Adding and removing requirements

Build requirements can be added to the aBOM if additional parts are required to be installed. This is the equivalent of redlining for aBOMs.

<figure><img src="/files/6Z9kvLHqpwkhS9EqmmXM" alt=""><figcaption></figcaption></figure>

As shown above, manually created build requirements can also be removed when editing the aBOM. If a build requirement is associated to a mBOM item, it cannot be deleted to help you compare the final aBOM state to the mBOM. You can, however, zero out the quantity of those build requirements you no longer need that are associated to mBOM items. Build requirements with a quantity of zero will not count towards the aBOM completion percentage.


# aBOM Beta Changes

## Benefits

* Increased Flexibility: Our updated aBOM will empower you to modify aBOM requirements, even if they originated from the mBOM. This will enable your teams to seamlessly incorporate changes on the fly and achieve 100% installation accuracy.
* More control: You will have the capability to edit reference designators and substitutes for each requirement separately from the mBOM.
* Simplified Integrations: The changes will make it significantly easier to listen for install/uninstall webhooks.

### API breaking changes

There will be breaking changes to the API. Please see the [subpage](/features/parts-and-trace/trace-aboms/abom-beta-changes/abom-actions-for-developers) if you are a developer on ION. We will also be sending out specific communication to those who are directly affected.

### Other ION changes

1. **New aBOM side panel**: we're introducing our newly design aBOM, which includes a streamlined interface to get to the information you need quicker and new options for uninstallation.

<figure><img src="/files/sFG4f8IRBClGX1v5b0Wa" alt=""><figcaption></figcaption></figure>

See below for a breakdown on how to use the new aBOM:

<figure><img src="/files/S7r3VK9NfmFmuh0uAynk" alt=""><figcaption></figcaption></figure>

When uninstalling parts, you will be presented with additional options including selecting a new location and scrapping the part being removed. Note: you can partially remove quantities and that will cause an inventory split.

<figure><img src="/files/zGRAYADqRsmjqrSxKYfo" alt=""><figcaption></figcaption></figure>

2. **Changes to the trace view**: the aBOM tree and indented views have had minor enhancements with the new updates.

Each build requirement will be shown in gray and show the total quantity required and the total quantity installed. Expanding that will show all of the installed parts.

<figure><img src="/files/I1ZBydVE4bQ4GUG1SeLf" alt=""><figcaption></figcaption></figure>

When exporting, only the installed items will be included (build requirements are skipped).

3. **You can edit build requirements (API only for now)**! This allows for changing the part, quantity, substitutes, reference designators, or whether it is Made on Assembly (MOA).
4. **mBOM to aBOM logic updates**: There are few small changes to how information is passed from the mBOM to the aBOM. Currently aBOMs look back to the mBOM items they were created from to get the substitute information and whether it is Made on Assembly (MOA). With this release build requirements will inherit substitutes and the MOA designation on creation, but will be allowed to change independently and may diverge from the mBOM item
5. **Install components onto untracked parts**: With this change we're allowing parts to be installed onto untracked parents.

Check out this video for more information:

{% embed url="<https://www.loom.com/share/977811bd80424a8ca0eb78b98fa2eabd?sid=37d4ae0f-569f-4b67-b142-07deece39dc3>" %}


# aBOM actions for developers

## Actions needed (for developers)

This project will introduce breaking changes.

1. **API**: If you are using the API to call any of the below mutations or a query that uses any of the below fields, you will need to update your mutations/queries.
2. **Actions**: If you have any ION actions (rules) using any of the objects below, those will be disabled when this project is released and you will need to update those after release.
3. **Webhooks**: If you have any webhooks listening to any of the objects below, you will need to update your webhook listeners after release.
4. **Analytics**: If you have any SQL queries referencing `abom_items` or `abom_edges` those will need to be updated.

If the above does not apply to you then no changes necessary!

## Changes overview

Below shows an example of a car assembly that is partially installed and the differences between the old structure and the new structure.

Old structure:

```mermaid
graph TB
  i1([
    inventory 1
    car assembly
    SN 45
  ])
  i2([
    inventory 2
    SN 12
  ])
  i3([
    inventory 3
    SN 13
  ])
  ab1[
    abom item 1
    car assembly
    qty 1
  ]
  ab2[
    abom item 2
    wheel assembly
    qty 1
  ]
  ab3[
    abom item 3
    wheel assembly
    qty 1
  ]
  ab4[
    abom item 4
    wheel assembly
    qty 2
  ]
  ab5[
    abom item 5
    fastener
    qty 50
  ]
  i1 --- ab1
  ab1 ---> ab2
  ab1 ---> ab3
  ab1 ---> ab4
  ab1 ---> ab5
  ab2 --- i2
  ab3 --- i3

  classDef green fill:#9f6,stroke:#333,stroke-width:2px;
  class i1,i2,i3 green
  
```

New structure:

```mermaid
graph TB
  i1([
    inventory 1
    car assembly
    SN 45
  ])
  i2([
    inventory 2
    SN 12
  ])
  i3([
    inventory 3
    SN 13
  ])
  br1[
    build requirement 1
    wheel assembly
    qty 4
  ]
  br2[
    build requirement 2
    fastener
    qty 50
  ]
  i1 ---> br1
  i1 ---> br2
  br1 --abom installation--- i2 
  br1 --abom installation--- i3

  classDef green fill:#9f6,stroke:#333,stroke-width:2px;
  class i1,i2,i3 green
  
```

Old structure:

* aBOM items represent both the requirement and fulfillment of the installation
* aBOM items are used to link to inventories
* aBOM edges connect aBOM items
* aBOM items change as items are partially installed/removed. New ones get created or deleted, or quantities change

New structure:

* Build requirements belong to parent inventories and represent what needs to be installed
* Build requirements do not change as items are installed into them
* aBOM installations link inventories to a build requirement. The addition of an aBOM installation is an install. The removal of an aBOM installation is an uninstall

## Mutation/query changes

* AbomItems will be replaced by `BuildRequirements` and `AbomInstallations`, where the requirement and fulfillment (install) are clearly delineated
* AbomEdges will be replaced by `PartInventoryBuildRequirements`

Below shows the full list of items that are going away.

### Going away

#### Mutations

* `InstallKitOnAbomItemChildren`
* `CreateAbomItem`
* `DeleteAbomItem`
* `UpdateAbomItem`

#### GQL Objects/Queries

* `AbomItems`
* `ABomEdges`
* `ABomItemReferenceDesignators`

#### Fields

* `PartInventory.abomItems`
* `PartInventory.abomChildren`
* `PartInventory.abomParents`
* `PartInventory.allChildren`
* `PartInventory.allParents`
* `Part.abomItems`
* `MBomItem.abomItems`
* `MBomItemReferenceDesignator.abomItems`
* `AbomItemReferenceDesignator.abomItem`

(and any count fields generated from these relationships)<br>

### Examples

#### API: Installing a part

Old structure:

Previously, you would have to update an existing `abom_item` with an inventory to install that inventory. The `abom_item` at that point may get swapped if the inventory being installed is already linked ot an `abom_item`

{% tabs %}
{% tab title="Update aBOM item" %}

```graphql
mutation UpdateABomItem($input: UpdateABomItemInput!) {
    updateAbomItem(input: $input) {
        abomItem {
            id updatedById partInventoryId
        }
    }
}
```

{% endtab %}

{% tab title="Inputs" %}

```graphql
{
    "input": {
        "id": 1,
        "partInventoryId": 1,
        "etag": "etag"
    }
}
```

{% endtab %}
{% endtabs %}

New structure:

Now installing a part is done via creating an aBOM installation. aBOM installations link inventories to `buildRequirements`. Conversely, uninstalling a part is done by deleting aBOM installations.

{% tabs %}
{% tab title="Create aBOM installation" %}

```graphql
mutation CreateABomInstallation($input: CreateABomInstallationInput!) {
    createAbomInstallation(input: $input) {
        abomInstallation {
            buildRequirementId
            buildRequirementReferenceDesignatorId
            partInventoryId
            quantity
        }
    }
}
```

{% endtab %}

{% tab title="Inputs" %}

```graphql
{
    "input": {
        "buildRequirementId": 1,
        "partInventoryId": 3,
        "quantity": 1
    }
}

```

{% endtab %}
{% endtabs %}

#### SQL: Query for an inventory's aBOM

Old structure:

```sql
select 
parent_part.part_number,
parent_part.description,
parent_inventory.serial_number,
parent_inventory.lot_number,
parent_inventory.quantity,
child_part.part_number,
child_part.description,
child_inventory.serial_number,
child_inventory.lot_number,
child_abom_item.quantity as 'installed quantity'

from parts_inventory parent_inventory
inner join parts parent_part on parent_part.id = parent_inventory.part_id
inner join abom_items parent_abom_item on parent_inventory.id = ai.part_inventory_id
inner join abom_edges ae on ae.parent_abom_item_id = parent_abom_item.id
inner join abom_items child_abom_item on child_abom_item.id = ae.child_abom_item_id
inner join parts_inventory child_inventory on child_abom_item.part_inventory_id = child_inventory.id
inner join parts child_part on child_part.id = child_abom_item.part_id

where parent_inventory.id = 105
```

New structure:

```sql
select 
parent_part.part_number,
parent_part.description,
parent_inventory.serial_number,
parent_inventory.lot_number,
parent_inventory.quantity,
child_part.part_number,
child_part.description,
child_inventory.serial_number,
child_inventory.lot_number,
ai.quantity as 'installed quantity'

from parts_inventory parent_inventory
inner join parts parent_part on parent_part.id = parent_inventory.part_id
inner join part_inventory_build_requirements pibr on pibr.part_inventory_id = parent_inventory.id
inner join abom_installations ai on pibr.build_requirement_id = ai.build_requirement_id
inner join parts_inventory child_inventory on ai.part_inventory_id = child_inventory.id
inner join parts child_part on child_part.id = child_abom_item.part_id

where parent_inventory.id = 105
```


# Inventory

ION Inventory allows you to keep track of your inventory, including locations, suppliers, quantities, serials, lots, and more.

### Philosophy

Our system takes a unique view to keeping track of your physical inventory. While other systems will add and remove items to inventory based on their physical availability, ION keeps the items as "inventory" and manages if they are available/installed/in progress via a status. This allows ultimate search-ability of parts. I.e. if you want to find where that specific serial number is.

With this approach, we encourage the creation of inventory as early as possible in the process. For instance, when creating a purchase line for a part, inventory is instantly created and put in an "On order" status. This allows you to pass serial information to the supplier if desired or create issue tickets against the serial number.

### Add inventory

![](/files/lTolcjijSkyRvUWxM3t9)

Use the "New Inventory" button in the top right of inventory to add inventory items. You can add attributes to each inventory item, including lot number, serial number, location, quantity, usage type, cost, and supplier.

Use the "New Part" button to create a new part in your part library.

Use the "Export to CSV" button to export your inventory lines to a CSV file.

### Lot number, serial number, and quantity

Inventory items can have lot numbers, serial numbers, and quantities set. Any inventory item that has serial number cannot have a quantity greater than 1. Serialized parts can have lot numbers, but lot-tracked inventory items need not have a serial number.

ION allows multiple inventory items, with different locations and different tracking attributes (e.g. lot, serial) even amongst the same part number.

### Locations

ION keeps track of your locations, so you can use the autocomplete to fill in which inventory location an inventory item or items are. You can manage already-created locations in the "Factory" section of ION.

### Suppliers

Suppliers work similar to locations. You can use the autocomplete to use an existing supplier or create a new supplier right within the inventory manager.


# Inventory status

## Overview

ION shows all part instances on the inventory screen even if they been consumed (installed, kitted) or scrapped. This allows for maximum traceability of parts as they move through the factory. Additionally, ION creates "inventory" as early as possible in the process, which is why inventory is created for runs and purchases before they are completed.

In order to manage this and allow you to see what inventory is physically available, ION uses an inventory status. The inventory status is calculated based on relationships in ION. Below shows the different options and logic associated with each.

<table><thead><tr><th width="146.33333333333331">Status</th><th>Meaning</th><th>Logic</th></tr></thead><tbody><tr><td><strong>Scrapped</strong></td><td>Full quantity is scrapped.</td><td>Scrapped quantity on the inventory record is equal to the inventory quantity.</td></tr><tr><td><strong>Installed</strong></td><td>Installed onto an assembly.</td><td>Full quantity is installed onto a parent aBOM.</td></tr><tr><td><strong>Kitted</strong></td><td>Actively kitted.</td><td>Kitted to an open kit (kit status not complete) AND not installed.</td></tr><tr><td><strong>WIP</strong></td><td>Linked to an active or failed run.</td><td>Inventory is attached to a run that is in a status of <code>todo</code>, <code>in progress</code>, <code>redline</code>, <code>hold</code>, or <code>failed</code>.</td></tr><tr><td><strong>On Order</strong></td><td>Linked to an active purchase.</td><td>Inventory is attached to a purchase line that is in a status of <code>draft</code>, <code>requested</code>, <code>approved</code>, or <code>ordered</code>.</td></tr><tr><td><strong>Unavailable</strong></td><td>Physically in inventory, but not able to be consumed based on location restrictions.</td><td>Inventory is none of the above states and the location that it is located in has its inventory availability turned off. OR the inventory quantity is 0.</td></tr><tr><td><strong>Available</strong></td><td>Physically available to consume.</td><td>Inventory is none of the above states.</td></tr></tbody></table>

The above table is sorted in order of how it is executed in the logic. For instance, if an item is `installed` and `kitted`, the `installed` status will take precedence.


# Inventory splitting

Understand and initiate inventory splitting

### How does it work?

When splitting an inventory, the original inventory has its quantity decreased. A new inventory is then created for the quantity difference. This new inventory copies over nearly all of the properties from the original inventory. It also maintains a link to original inventory that is called `originPartInventoryId` in the API.

<figure><img src="/files/PjUV43pzKHqjPG9knuZq" alt=""><figcaption></figcaption></figure>

### Initiating an inventory split

You can manually split an inventory via the inventory or receipts views.

When splitting, you have 2 options:

1. **Split** - Splits a single item into 2 items by specifying a quantity. Example: Inventory is quantity 10 and you want to split off one for qty 3.
2. **Split Many** - Splits a single item into multiple items by specifying the number of items desired. Example: Inventory is quantity 10 and you want to create 10 inventories of quantity 1.

<figure><img src="/files/p4KaeLaCle0p2NRwf48X" alt=""><figcaption></figcaption></figure>

### Automated splitting

ION will automatically split inventory when partially installing, kitting, or scrapping a quantity. This occurs to keep the location/status of inventory items correct. For instance, if you have an inventory for quantity 2 and you kit 1 item, the inventory will split. Now the item that has been kitted will properly show a "Kitted" status and its location can be updated from the original.

For the purpose of barcodes, it is good to know how the new inventory is created. This table below shows how the inventory is created:

| Action                 | How should the inventory split take place |
| ---------------------- | ----------------------------------------- |
| partial kit            | New inventory for the kitted item         |
| partial unkit          | New inventory for the unkitted item       |
| partial install        | New inventory for the installed item      |
| partial uninstall      | New inventory for the uninstalled item    |
| partial scrap          | New inventory for the scrapped item       |
| partial unscrap        | New inventory for the un-scrapped item    |
| direct inventory split | Qty to split becomes new inventory item   |
| partial receive        | New inventory for received item           |
| partial unreceive      | New inventory for unreceived item         |

### Carrying information across split inventories

Inventory relates to a lot of different objects in ION: runs, kits, issues, purchase lines, etc. Runs and issues only allow 1 inventory item to be related to them. When an inventory that is tied to a run (or issue) is split, it will use the **origin part inventory** information to maintain a reference to the run/issue.

For the inventory items shown below, the inventory was added to a run and then there was an issue tied to it. When that inventory was split, the new inventory created maintains a reference to both the run and the issue (see "Appears on" and "Issues" columns).

<figure><img src="/files/o4vtkOKzcCnAXe5mx0Ma" alt=""><figcaption></figcaption></figure>

This is also reflected on the aBOM within the trace view:

<figure><img src="/files/tzfOv5wwXkcNLtaojIe8" alt=""><figcaption></figcaption></figure>

### What happens to installed inventory and build requirements?

Please review [Split Inventory on a Run](/features/runs/split-inventory-on-a-run) for more information on splitting an inventory item with installed inventory on the aBOM.


# Inventory merging (org setting)

This organizational setting drives the Merge Inventories function by automatically consolidating identical part inventories from multiple receipts and purchase orders into a single inventory record.

This feature can be switched on and off by navigating to your Organization Settings in ION and selecting 'Merge Inventories (V2)', as shown below:

<figure><img src="/files/CyvCGMubsQJB48naHUUX" alt=""><figcaption></figcaption></figure>

This functionality was developed to address the following challenges:

* Manually managing separate inventory items for the same part across different POs and receipts
* Multiple barcodes for identical parts lot tracked/untracked parts
* Unnecessary inventory lines cluttering the system
* Digital processes don't match real-world warehouse operations

This feature provides the following:

* "Dump More Bolts in the Bin" - mirrors real-world warehouse operations where untracked and lot tracked COTS parts are naturally consolidated into single locations or bins,
* Single Source of Truth - One barcode, one location, one inventory record
* Seamless Consolidation - Automatically merge identical parts without losing traceability to purchase orders and receipts

### **Use Cases**

#### ✅ Use Case 1: Multiple Receipts, Different Purchase Orders

* Scenario: Same part received on different dates from different suppliers
* Example: 50 bolts received on Monday from Supplier A, 25 bolts received on Wednesday from Supplier B
* Result: Automatically merges into single 75-bolt inventory with one barcode

#### ✅ Use Case 2: Multiple Receipts, Same Purchase Order

* Scenario: Same part received in multiple shipments against the same PO line
* Example: 100 widgets ordered, received in 3 shipments (40 + 35 + 25)
* Result: Consolidates into single 100-widget inventory while maintaining PO traceability

#### ✅ Use Case 3: Non-PO Inventory Integration

* Scenario: Additional inventory received without purchase order association
* Example: Customer returns, engineering samples, or transferred inventory from other locations
* Result: Seamlessly rolls into total available inventory count

### Details

**Note:** If Merge Inventories V1 is also turned on via the feature flag, and the the V2 org setting is switched on, inventory will be merged according to V2 logic (discussed below).

#### How to trigger merging:

* By making a change to a part inventory in the Inventories page. This workflow can be seen in the video below, along with a general overview of the merge functionality

{% embed url="<https://www.loom.com/share/39560d85016c4a85843591e6e5ba9011?sid=f4b21ffa-0803-457a-ac01-b047b9392fab>" %}

* By *partially* kitting an inventory item, as shown in the picture below. The fact that the selected amount (shown in the blue box below) is less than the available amount (shown in the green box below), indicates that a partial kitting operation will occur. The merge occurs on the remaining un-kitted inventory.

<figure><img src="/files/RiVVKKhBMAn8Bdslq9gk" alt=""><figcaption></figcaption></figure>

* By unkitting an inventory item
* Installing inventory (Partial)
* Uninstalling inventory
* Removing inventory from an Issue

**Note**: Currently, merging is only triggered by customer interaction with the UI and not by any actions from scanning.

#### Merge criteria

In order for inventory items to be eligible for merge, the inventory candidates must have:

1. Same underlying part id; part must be of type 'part' and not a tool
   1. Tracking type can be untracked or lot tracked, but cannot be serial tracked
   2. If part is lot tracked, lot IDs must match
   3. A part inventory with an assigned serial number will not be merged, even if the underlying part is not serial tracked
2. The same location, and location must be set (i.e. two inventories with no location assigned will not merge)
3. The same status, and status must be 'available' or 'unavailable'
4. The same unit of measurement
5. Merge candidate cannot be installed on another inventory's aBOM
6. Merge candidate cannot have installations on its aBOM
7. No related purchase order lines that are in 'canceled' status
8. No related runs
9. No related origin runs
10. No related issues
11. No related part kits
12. No related plan reservations
13. The quantity kitted and the quantity installed both should equal zero
14. Must not be a 'Part used to fix issue' on an issue related to another inventory

### ⚠️ Important Limitations:

Merge will NOT occur when the same part is referenced on different purchase order lines within the same receipt.

Relationships currently existing between merge candidates and the following objects may block a merge, resulting in an error (but no change in data) or may be lost during merge:

* build\_requirements
* run\_steps
* part\_kit\_items
* origin\_mbom
* part\_inventories
* made\_on\_assembly\_child\_part\_inventories
* made\_on\_assembly\_parent\_part\_inventory

Additionally, foreign key references for part inventory id will not be updated in the following places:

* part\_inventories\_attributed\_parts
* part\_inventories\_attributed\_users
* part\_inventories\_requirements
* build\_requirement\_reference\_designators

On inventories created through a merge from inventories that have related purchase orders with different suppliers, the supplier on the inventory will be equivalent to one of the multiple suppliers associated with the merge candidates. Not all of them will be reflected on the merged inventory itself, as shown in the query below. Also in the query below it can be observed that all supplier ids associated with a merged inventory can found by looking at related purchase order lines:

![](/files/D8covLI6shAZb6x5m1Sc)

If a part inventory was created by a split from an inventory that ended up being a merge candidate, but the inventory in question was later excluded from merge candidacy (i.e. moved to a different location, having an issue opened against it etc.), that inventory will be excluded from merge, but when looking at its transaction history post-merge, it will appear that the inventory has been merged when it has not:

<figure><img src="/files/MV2sX657IBEmK4NvFREW" alt=""><figcaption></figcaption></figure>

Additionally, there may be other incorrect or incomplete transaction history line items related to an inventory being merged in this UI.

Finally, looking up transaction history on an inventory that has been merged (and thus deleted) will show an error in the UI, though the transaction history for that inventory will be available.

<figure><img src="/files/heSzudCTmvWqq0ERDcVO" alt=""><figcaption></figcaption></figure>

**Differences from Merge Inventories set through Feature Flag:**

1. Criteria for assessing merge candidates for a given inventory has changed (see above)
2. Upon merge, a new part inventory is created and the part inventories to be merged are deleted
   1. Each custom attribute that has the same value across all merge candidates will have the value copied over to the new part inventory
   2. Comments, file attachments and labels are copied over
   3. No transaction history will exist prior to the merge for the newly created merged inventory (traceability to related PO lines and receipts is maintained)
3. Old barcodes for the inventories that were merged in will now point to the new merged inventory


# Inventory merging (legacy)

Merge inventories together based on physical and data conditions as seen below to simplify inventory management in your factory inventory.

{% hint style="info" %}
If you need to enable or disable this functionality please reach out to your First Resonance representative.
{% endhint %}

Merging inventories is initiated by an update to an inventory item. This feature is on by default and can be turned off per your organization needs - please let us know if you want it turned on/off! This is available if you have accidentally split inventory, or in general for inventory that you would like to merge.

This video shows how merges take place within the application:

{% embed url="<https://www.loom.com/share/5c669c98b2f44184b7359e814250a8eb>" %}

**Note**: Merging is only triggered right now by manual updates on the inventory interface and not by any actions from scanning.

#### Merge criteria

In order for items to be eligible to merge, the inventories must have:

1. the same part, lot number, location, supplier, and unit of measure
2. the same status(i.e. available, installed, etc.)
3. no serial number
4. no aBOM(as-built bill of materials)
5. no associated issues
6. no associated runs
7. the same custom attributes
8. be associated with the same purchase line item (if tied to one at all)
9. be kitted to the same kit (if kitted)
10. be received on the same receipt line (if received)

#### Combined fields on merge

Comments, labels, and file attachments are all combined when two inventories merge into one.

#### Printing barcodes

When the inventory is merged there is an option to print a new barcode label.

<figure><img src="/files/ZAoliJqdAFzInMBxADv2" alt=""><figcaption></figcaption></figure>

The barcode for the older inventory will still work, but the barcode for the newer inventory will no longer work because that inventory has been deleted.

Printing a new barcode label ensures you are using the correct label and also reflects the new quantity on the label if you show quantity on your inventory barcode label.

#### Merge history

When an inventory merges, you will see the quantity update in the inventory history. Currently, we're not showing you any information specific to the merge, but we will be including that in a future update.

<figure><img src="/files/l0TeBKfz7pSdJn1esBRg" alt=""><figcaption></figcaption></figure>


# Inventory scrapping

### Overview

ION allows you to explicitly scrap inventory, making it unavailable for use. You can scrap inventory in a few different ways, as outlined below. Additionally, if you’re scrapping only part of a lot, there is functionality to handle partial quantities.

### Functionality

#### Scrapping Partial Quantities

Regardless of where you scrap inventory, if you scrap less than the full quantity, the inventory will automatically be split. For example, a lot-tracked inventory item with a quantity of four can be split into two lines: one with a quantity of one (scrapped) and another with a quantity of three (remaining in its original status). All lot traceability remains linked to the newly created line, ensuring clear visibility of the scrapped parts' history.

#### Scrapping on Uninstall

If you know the inventory will be scrapped during uninstallation, you can scrap it directly from the uninstallation screen. Simply select the quantity to uninstall (if applicable) and check the "Scrap" box before submitting the pop-up.

<figure><img src="/files/dvAtsL4X9JDTdIK9LLRq" alt=""><figcaption><p>Scrap on uninstall.</p></figcaption></figure>

#### Scrapping From Inventory Page

You can also scrap inventory directly from the inventories page by editing the "Scrapped Qty" column. If the entire quantity is marked as scrapped, the status of the entire line will change to "Scrapped." If only part of the quantity is marked as scrapped, the system will apply partial scrapping logic, creating a new inventory entry to reflect the partially scrapped quantity.

<figure><img src="/files/ULm2v0rxTV3KkeNrcCpw" alt="" width="172"><figcaption></figcaption></figure>

<figure><img src="/files/dD8frBl3pc22rlpMw2bd" alt=""><figcaption></figcaption></figure>


# Kitting

## What is a kit? <a href="#what-is-a-run" id="what-is-a-run"></a>

A Kit is a collection of parts that is reserved to be used on a specific run. As you kit components they are automatically taken out of inventory. Using kitting allows you to plan your assemblies without worrying about double dipping your inventory!

## Creating a kit <a href="#creating-a-run" id="creating-a-run"></a>

### New run page

In order to create a kit, it needs to be attached to a run. On the run page, as you fill out the required fields (shown below) the "Prepare Kit" button will become active.

![](/files/VY9CcbtY7O6GdPW827Ky)

When you press the "Prepare Kit" button ION will use the mBOM stored in the parts section to determine what parts could potentially go into the kit. These parts and quantities will show up in the kitting view.

![](/files/4yBM8g32f5muxUsmat3M)

### Kitting Page

In the kitting view, you will be able to select serial or lot numbers of the kitable components to add them to the kit.

![](/files/haQgphTNksjAafI4bv82)

### Kitting Run

The run that a kit as assigned to is in the run left hand corner of that kit, below the kit number.

![](/files/b5KR3XFqABw4C4vsnnYn)

To change the run that the kit is assigned to, click on the Run number from the page (in this case, click on the text Run-882). It will change to a dropdown menu. From there you can select the new run to attach the kit to.

Here's a quick video for how to change which run a kit is assigned to:

{% embed url="<https://www.loom.com/share/7d21c9a097424190ba5f744841eb9ced?focus_title=1&from_recorder=1>" %}

Because the purpose of kitting is to reserve parts for a specific run, as soon as the parts are kitted they are subtracted from inventory and attached to a specific run. It is also not required to fully kit all parts.

*See* [*Part Inventory and Kitting in the API*](/api/examples/part-inventory-and-kitting) *section for more information.*


# Inventory Movement Automations

ION has a few, high confidence inventory movement automations built in to allow you to quickly move inventory throughout your factory and reliably keep your data clean and up to date.

We have broken down the automations into three main areas. These automations work with each other so to understand the complete workflow, take a look at the diagram below!

### Kitting

* When kitting inventory, if the kit's **Current Location** is set, then the kitted inventory's location is updated to the kit's current location.
* When moving the kit's **Current Location**, the kitted inventory will move with it.
* When changing the status of the kit to DELIVERED, update the **Current Location** of the kit to the **Deliver To Location.** Coupled with the above, this means all of the kitted inventory will move to the Deliver To Location.

### Installation

* When installing inventory, the installed inventory's location is updated to the assembly's location.
* When moving the assembly, all installed inventory moves with it. This occurs through the whole depth of the aBOM.

### Runs

* When starting a Run Step, the WIP assembly is moved to the location of the Run Step. If there is installed inventory on the WIP assembly, they will also move as discussed above.

### Full Workflow

<figure><img src="/files/WPlnHjdCRvuHne3TDwky" alt=""><figcaption></figcaption></figure>


# Manufacturing bill of materials (mBOM)

### Editing the mBOM

The mBOM can be created/updated within the part library.

<figure><img src="/files/dAf8CHEU8rvzyyOjvQzk" alt=""><figcaption></figcaption></figure>

You are able to define only one bill of materials per part/revision. We recommend creating a new revision for the part if you have an update to the mBOM.

In addition to part and revision, the following attributes can be managed on the mBOM:

* **Made on Assembly (MOA)**: If true, it means that this assembly gets built on the same process with its parent. [More on MOA here](https://manual.firstresonance.io/features/parts-and-trace/manufacturing-bill-of-materials-mbom/made-on-assembly-moa).
* **Substitutes**: Parts that can be used interchangeably on this bill of material. This will allow other parts to be installed/kitted further down in the process.
* **Reference designators**: Defined positions in the mBOM that you'd like to maintain during installation. [More on reference designators here](https://manual.firstresonance.io/features/parts-and-trace/manufacturing-bill-of-materials-mbom/reference-designators)
* **Quantity:** This is the minimum inventory quantity that needs to be installed to satisfy a build requirement on the aBOM. Suppose the mBOM quantity is set to 0. In that case, technicians can select untracked or lot-tracked inventory without selecting the installed quantity, which is ideal for **consumables** where only the trace information is relevant and not the quantity. Because the technician can always install more quantity than the requirement suggests, we recommend using this functionality for **As-Required** materials where you do not know the precise installed quantity in advance.
  * **Consumables** may include epoxies, kapton tape, or other cleaning materials.
  * **As-Required** materials may include carbon fiber layup and powder.
  * [Here is a click through ](https://firstresonance.storylane.io/share/pg6kczca07vm)to see this in action.

### Editing the mBOM by exporting the mBOM

You can click on `Go to full mBOM` above and choose to export the mBOM as a CSV, make your edits in the spreadsheet, and re-import your mBOM into ION.

The mBOM will export in `Level notation`, so when you import it, make sure you choose that option!

### Importing the mBOM

There are two options for importing BOMs - Depth Notation and Level Notation. With depth notation, if you accidentally disorganize your CSV file, you may have mBOMs that don't match eBOMs. See below for an example. The Equivalent "Level" notation is on the right hand side.

[![](https://downloads.intercomcdn.com/i/o/752922318/69867f9dcf743990535da22d/image.png)](https://downloads.intercomcdn.com/i/o/752922318/69867f9dcf743990535da22d/image.png)

In this format, the level 1 is the top level, all the 2s are the next level down, 3s are the next level down from there, etc. But the order matters - if you moved the 3s underneath a different 2, the mBOM would change significantly. Therefore, it is important to make sure that your BOM is in the correct order and has not been rearranged since exporting it from your PLM/CAD software.

In Level notation, 1 is the top level assembly, and 1.1, 1.2, 1.3, 1.4, 1.5 are children of that assembly. 1.1.1 and 1.1.2 are children of 1.1, and 1.1.1.1 is a child of 1.1.1. See example below where the BOM was copied into the table as "manually imported data". Here you also have the option to import your parts via a CSV, TSV, or TXT file.

#### mBOM Importer Behavior

The mBOM Fast Importer handles draft Bill of Materials versions more predictably and transparently, with the following logic.

**Behavior Overview**

* **AlwaysCreateNewVersion = TRUE**
  * A *new* Draft mBOM version is always created before importing.
  * Items from the CSV are imported into this new draft.
* **AlwaysCreateNewVersion = FALSE**
  * **If a Draft mBOM already exists:**
    * The importer **overwrites the existing draft**, deleting all items in that draft and replacing them with the items from the CSV.
    * Missing CSV items are fully removed.
  * **If no Draft mBOM exists:**
    * A new Draft mBOM version is created and populated with imported items.

\
This update ensures mBOM imports behave consistently across organizations, preventing stale or duplicated draft data and giving clearer control over when new draft versions are created.

#### Faster mBOM import options

{% hint style="info" %}
Because a fast option exists and is more reliable, the "Slow" importer will be deprecated by the end of 2025.
{% endhint %}

There are options to use a faster import that does not have preview capabilities, but will allow BOMs to be imported much faster than our standard options. Check out the below video for more information.

{% embed url="<https://www.loom.com/share/69365b3c4eee4c8eb30c1c38d31a480d?sid=ba58e87b-b1eb-4c2f-acea-8f62c54b93e7>" %}

### Substitutes

Substitutes should be in the format:

PartNumberA\[X];PartNumberB\[Z]

Where X and Z are the revisions for PartNumberA and PartNumberB

### Transfer to the aBOM (As-built bill of materials)

When an inventory is created for an assembly with a serial number or lot number, that triggers an empty aBOM to be created from the mBOM. Each item in the aBOM maintains a link to each item in the mBOM and it's called the `originMbomItemId`. The aBOM uses this relationship to reach back to the mBOM for information such as substitutes and if the part is Made on Assembly.

### Full visualization of the mBOM

Use the `Go to full mBOM link` to see entire mBOM in tree or indented views.

<figure><img src="/files/KZbDngRUQ6sTDpi9G0os" alt=""><figcaption></figcaption></figure>


# mBOM versions

Control changes to mBOMs with versions, with statuses and approvals

## What are mBOM versions?

mBOM versions allow for many mBOMs ***per part revision***. mBOM versions do not go across part revisions. If a new part revision is created, it will always start as mBOM version 1.

Use mBOM versions when needing to introduce controlled changes to the mBOM in the same way that procedure versions are used. Like procedure versions, mBOM versions have a status (`Draft`, `In review`, `Released`, `Archived`). Approvals can be added to mBOM versions when progressing to `Released`. They use role-based approvals and individuals or teams can be requested to review.

mBOM versions are feature-flagged and we can turn it off/on for you environment.

<figure><img src="/files/ogqMHDIbJmv4ZNXsddpI" alt=""><figcaption></figcaption></figure>

## Creating a new mBOM version

If a new part revision is created, it will generate a draft mBOM (version 1) from the previous part revision. For a newly created blank part, an mBOM version will be created as you start to populate the mBOM.

If there is already a released version of an mBOM for a given part number, a new version can be created from the status dropdown (as shown below):

<figure><img src="/files/NWtJBvvjAZC2zZjwEZgR" alt=""><figcaption></figcaption></figure>

## Reviews

From draft, the status of the mBOM version can be updated with the status button dropdown. From there, reviews can be requested as shown below. Reviewers will approve in the same way by clicking on the `Reviews` button.

<figure><img src="/files/8gTUGu5gAF3SOFHKUgQ1" alt=""><figcaption></figcaption></figure>

#### Required approvers

Required approvers can be configured through the API only (for now).

{% code lineNumbers="true" fullWidth="false" %}

```graphql
mutation CreateMBomApprovalRole($input: CreateMBomApprovalRoleInput!) {
  createMbomApprovalRole(input: $input) {
    approvalRole {
      _created
      _etag
      _updated
      count
      createdById
      gateType
      roleId
      updatedById
    }
  }
}

{
  "input": {
    "roleId": 3,
    "count": 1,
    "gateType": "RELEASED"
  }
}
```

{% endcode %}

In the above example, it will require 1 approval from `roleId` 3 before the mBOM version can be released.

## aBOMs/Autoplan logic

When an inventory is created for a given part number/revision, it will create aBOM requirements based on the latest released mBOM version. If there are only draft mBOM versions, then it will use the latest draft mBOM.

Autoplan uses the same logic to determine the mBOM version that it should use to drive demand.

For now, the mBOM tree view will also use this logic to determine which parts to show.

<figure><img src="/files/2EQcXDQcEm4kRkgGIgT5" alt=""><figcaption></figcaption></figure>

## Rules

Below shows a list of rules related to mBOM versions:

* An mBOM version can go from released to draft only if no aBOMs have been created from that mBOM
* Multiple mBOM versions for a part/revision **CAN** be in draft at the same time
* mBOMs can only be approved while the mBOM version is in an `in review` status


# Made on Assembly (MOA)

Design your mBOM to build multiple levels of an assembly on the same work instructions.

### Overview

Made on Assembly is a useful tool for the cases where a single procedure will always build two or more levels of an mBOM. Consider the mBOM below:

```mermaid
graph TD
  A --> B --> C
```

If based on the workflow, part B is built in the process of building part A, and there is no need to inventory part B separately, it might make sense to set part B to MOA. The information below will show how Made on Assembly is handled across ION and help you decide which parts should be designated as MOA.

### MOA Frequently Asked

Here are some other notes on MOA:

* **Where can MOA be set?**: toggle MOA on the mBOM via the part library
* **How can the grandchildren parts be installed?**: multiple levels of the aBOM can be accessed via the aBOM manager on a run
* **How are MOA inventories generated?**: part inventories are autogenerated for the MOA part when the aBOM is created (if serial-tracked, serial number is autogenerated, otherwise will autogenerate a lot number)

### MOA in aBOMs

Defining as assembly as Made on Assembly will allow you to build the aBOM for that assembly while building the parent.

In the example below the wheel assembly has been set to be MOA in the mBOM.

<figure><img src="/files/QOrVSwjXWpFICQLzXHsP" alt=""><figcaption></figcaption></figure>

The expanded mBOM for the car assembly looks like this:

<figure><img src="/files/rYdKdVzNW5fAduVc29F3" alt=""><figcaption></figcaption></figure>

When a run is created for the car assembly (part number 12345-01-01) and the aBOM is opened, you'll notice 2 things:

1. An inventory item has been created with an auto-generated lot number for the Made on Assembly (MOA) part.
2. You can install the children for the wheel the assembly. This allows you to build multiple levels of the aBOM in one process!

<figure><img src="/files/jLcvZuNykL7gBFHdBwOX" alt=""><figcaption></figcaption></figure>

From here, you can proceed to install components as usual.

### MOA in kits

When kitting an assembly that has MOA assemblies, MOA parts are not included in the kit, but their children are.

This kit was generated from the same mBOM as above. Notice how the wheel assembly is not an item, but the tire and wheel hub parts are.

<figure><img src="/files/drz7kgPxflJYaMNkjlUQ" alt=""><figcaption></figcaption></figure>

### Made on Assembly philosophy

The reason that we construct multiple levels of the aBOM for MOA parts is so that you can remove MOA assemblies easily.

For instance, in the example above, if you were to remove the wheel assembly later on after it had been built, its children would also come with it. If we were to flatten the BOM to include the children parts, you would have to remove each child part (tire and wheel hub) individually.

### Made on Assembly in Autoplan

In Autoplan, Made on Assembly components will be marked as `Placeholder` within the plan results. `Placeholder` items cannot be converted directly into runs/purchases. They are purely there to fully represent the hierarchy of the BOM, but they should not be actioned themselves.

<figure><img src="/files/uZQjr0zqzh3RL4a9Px5h" alt=""><figcaption></figcaption></figure>


# Part Substitutes

Part substitutes can be added in this fashion:

* Navigate to the part library item
* Click on the area that says `No Substitute Parts`. The area will change.

1. ![](/files/ofQkK85TQLVuwXIcXv0E)
2. ![](/files/2sObSDBXULN7UyfrScxA)

Once the substitutes have been selected, click the checkmark to confirm and save.

![](/files/yBKPOQ8VFo2BZwWNCaft)


# Reference designators

Define positions in the mBOM that are useful for installation traceability

### Overview

* Define reference designators in the mBOM
* Install inventory into reference designator positions in the aBOM
  * aBOMs will fan out to represent the number of reference designators

### Example

In the assembly below, there are 8 lidar, 8 radar, and 3 camera sub components.

<figure><img src="/files/vgqLGLPEuAcgmY5tQo0d" alt=""><figcaption></figcaption></figure>

To define positions for the camera click the `Add` button in the Reference Designators column as show below:

<figure><img src="/files/tUaICXBgIfUTSVCsh5Ak" alt=""><figcaption></figcaption></figure>

When the aBOM is generated, the reference designator will appear above the inventory selector for the camera items. Inventory can now be installed into specific positions. Note that 1 aBOM item was created for each reference designator.

<figure><img src="/files/0Lh8kRZMqEDvNLTGrmy0" alt=""><figcaption></figcaption></figure>

Reference designators are also reflected in the trace view:

<figure><img src="/files/OkTZUEeO3yHGTPbX2J39" alt=""><figcaption></figcaption></figure>

### Rules/Validations

* You can not define more reference designators in the mBOM than quantity
* When creating aBOM items for reference designators, each aBOM item is created for quantity 1


# Part Attributes

Part attributes allow you to add custom fields to the parts in your part library

## What are part attributes

Manufacturing can be a complex business, and there are sometimes part qualities and requirements you might want to track at a part level such as if a component requires an incoming quality check. Part attributes allow you to define custom parameters at a global level in your ION environment.

![Different types of example atributes](/files/-MJURL_vm5LCe_yjux_v)

### Setting up part attributes

1. Go to your environment's settings by clicking on the gear in the lower left-hand corner of the ION home page.

![](/files/RBUlKY3S1BCpnE1W4hTL)

2\. Go to the Organization tab

![](/files/B0Iww1QuXD3ym8UJpjho)

3\. Scroll all the way to the bottom of the page and you will see the section that allows you to add part attributes.

![](/files/lnqYHziceEPEBIlJ3Uk0)

4\. Choose the type of attribute you want to create from the drop-down menu. Please note that this attribute is a global property and will appear on all parts in your library.

![](/files/-MJVklVG6ZkxRXQZNZlD)


# Part revision interchangeability

ION supports part revision interchangeability out-of-the-box

If your organization has a policy that all revisions for the same part number are fully interchangeable, you can configure ION to follow suit.

{% hint style="info" %}
Use this functionality when your organization enforces that part numbers have the same form, fit, and function and uses different part numbers when not the same form, fit, and function.
{% endhint %}

Toggle on this option in organization settings (/settings/organization).

<figure><img src="/files/L5ARLmsZZHP6Jq4GcyfM" alt=""><figcaption></figcaption></figure>

Once enabled, while kitting or installing, you will be able to consume inventory that has the same part number as the required part even if it's a different revision.

Note the aBOM below, where Rev C is required, but a Rev B has been installed.

<img src="/files/i8DyjEkvY12Af69RnKfb" alt="" data-size="original">


# Supplier Part Numbers & Purchase Unit Conversions

Create relationships between your internal parts and suppliers that help effectively communicate supplier part numbers and supplier units of measure

{% embed url="<https://www.loom.com/share/f11eefba4dc94bbfab94875c4375dc8c?sid=fc13664d-b2c3-4141-aaca-531fe359d347>" %}

The new supplier part number feature will enable you to create relationships between ION parts and the supplier parts from which they can be sourced. Within this new screen, you can set up the relationship between part and supplier, a supplier part number, and a unit of measure conversion between the supplier part number and the ION part.

{% hint style="info" %}
These units of measure conversions only apply to purchases.
{% endhint %}

<figure><img src="/files/cn1yC2uHSQUgXJmM9ewM" alt=""><figcaption></figcaption></figure>

### Example Use Case

Here is an example of what that supplier part number configuration screen could look like for an internal wire part and roll-based supplier part. The ION part has feet specified on its library record, which is the unit that will be used on an mBOM and ultimately consumed on an aBOM. The roll from Absolute Precision has 100 Feet in it. When the buyer purchases the internal part they will have a new column called Supplier Part (shown below) which allows them to pick the supplier part number associated with that supplier <> ION part combination. In the case above, the buyer should populate the **quantity of rolls**, not feet, to be purchase&#x64;**.** Along these same lines, you should be putting the roll cost into the unit cost field not the per foot cost.

{% hint style="info" %}
The inventory (with the status of On Order) associated to the purchase order line will show as the inventory unit of measure while the purchase order line will show as the supplier unit of measure.
{% endhint %}

In the above case, the inventory will show as feet while the purchase order line will show as rolls.

<figure><img src="/files/AyxrBK1xMLVRManny4SE" alt=""><figcaption></figcaption></figure>

This feature will enable purchasing teams to buy in aggregate quantities while allowing downstream activities to consume the proper amounts.

## Setting a supplier part number on the parts screen

On the part side panel of a part in the library, press the "Associated Supplier Part Numbers" dropdown to see existing supplier part numbers associated with that part or create a new one by pressing the "Create new" button. When you enter this part on a purchase order with a recognized supplier you will be prompted to select from this predefined list of supplier parts.

<figure><img src="/files/cKra5Xk6ywP3wKSVPHqD" alt=""><figcaption></figcaption></figure>


# Kitting and Inventory Fulfilment

Kitting allows you to request and fulfill inventory. In general, it quickly allows you to add inventory to the kit and bulk move all of the inventory to a location when you deliver the kit with ease. It can be used to allocate material to a run or for workflows that may not require a run such as getting parts for engineering testing, delivering lineside materials, or automatically generating kits to backfill line-side quantities.

First, create your kit and [request parts for the kit ](/features/kitting/inventory-requests)by clicking on the `Add parts from mBOM` button as seen below. Alternatively, request parts one by one by clicking on the `Add part` button. Once you have requested the parts, set the ***deliver to location***.

<figure><img src="/files/2NgAMqDyaGoWTxtLgkT7" alt="" width="563"><figcaption><p>Click the Add Part or the Add Parts from mBOM to request Parts</p></figcaption></figure>

## Kit Fulfillment

We recommend when in charge of fulfilling kits, that you have a screen for all inventory specialists that refreshes newly requested kits every minute to ensure kits are delivered in a timely manner.

To fulfill the kit, ION currently supports these two workflows:

### Digital First Kits

In this method, you will digitally kit all of your inventory before physically kitting your inventory. The advantage of this method is that you can create a location pick list for your kit to help you understand where to source materials from in your warehouse.

1. Open the kit and begin digitally kitting the inventory needed for the kit. Click the dropdown and select the lot number(s) or serial number(s) needed to fulfill the requested part.<br>

   <figure><img src="/files/C4JnXAK6roOFbM6eJi6F" alt=""><figcaption><p>Select the inventory you want to digitally kit</p></figcaption></figure>

   If you have multiple locations for inventory, pull up the inventory screen on another screen or tab to determine which location you want to kit the inventory from.
2. Once you have digitally fulfilled the kit, click the `See all inventory from kit` button and sort the [inventory](/features/parts-and-trace/inventory) by location. When bulk printing the barcodes, they will now print in an order that serves as your pick list. Ensure the [barcodes have the](/features/barcode-labels) location for the digitally kitted inventory to help the inventory specialist know where to go to kit the inventory needed.

{% hint style="info" %}
Name your locations so that when sorted alphabetically, it gives inventory teams an order to kit inventory in.
{% endhint %}

{% embed url="<https://www.loom.com/share/bd3653b7f4244638aced41278c5a63a0?sid=af92affa-dda1-42c9-80af-201e218a9945>" %}

3. Now that the inventory is physically kitted, set the ***current location*** of the kit to set all of the inventory in the kit to that location. Finally, follow the [Inventory Movement Automations](/features/parts-and-trace/inventory/inventory-movement-automations) to ensure the inventory location reflects the delivered location after the kit has been delivered.

### Physically First Kits

In this method, you will physically kit all of your inventory. The advantage of this method is that if you know where your inventory is, scanning the inventory into the kit is a more accurate and faster method.

1. Open the kit, set the kit's ***current location***, and print the kit barcode. Place this kit barcode on the tote or cart that you plan to use to deliver the inventory. We recommend bringing your iPad or tablet on the cart with you to ensure scanning works accordingly.
2. Using a scanner connected to an iPad or tablet, [scan the inventory](/features/barcode-labels/scanning) you want to kit by scanning the inventory and then scanning the kit barcode.
3. Follow steps 2 and 3 above to printing the new kitted inventory barcodes and deliver the kit.


# Kit Statuses and Workflows

The kit has predefined statuses to help you speed up your inventory delivery

Below are the various stages of a kit and how to make the most of them. Remember, you can move from any status to any status in ION

**Draft:** This is the default status of a newly created kit. As a manufacturing engineer or technician, you should use this status when filling out parts that you need at the lineside or at any other location. At this stage, set the *deliver to location* of the kit.

**Requested:** Once the creator of the kit has finished determine what parts are needed and where, then set the status of the kit to requested. Inventory teams can filter for kits that are requested to understand which are ready to be actioned on. At this stage, you can assign the kit to the appropriate team member to fulfill.

**In Progress:** Once you are kitting the relevant inventory for a kit, mark the kit as in progress to show both other inventory personnel and the kit requestor that the kit is already being worked on. Kitted inventory will be marked with the [kitted](/features/parts-and-trace/inventory/inventory-status) status.

**Delivered:** After delivering the kit, mark the kit as delivered. This will set all of the inventory in the kit to the location of the [kit's *deliver to location* automatically.](/features/parts-and-trace/inventory/inventory-movement-automations)

{% hint style="info" %}
See [Inventory Movement Automations](/features/parts-and-trace/inventory/inventory-movement-automations) for more details.
{% endhint %}

**Completed:** If you need to return a kit ot part of a kit back to your warehouse, mark the kit as completed. This will mark the inventory that has not been installed as available. This however will not change the location of the inventory that is being returned. You can use the current location of the kit to change location of the kitted inventory all at once.

**Canceled:** When a kit is no longer needed, mark it as canceled.


# Inventory requests

Kits can be used to request inventory from the warehouse via the inventory and library views.

Populate information such as:

* Where you'd like the parts delivered to
* Which parts/quantities you need
* The status (Draft, Requested, In progress, etc)

![](/files/UAMBCh0eDghbhsdgoi9k)


# Kitting and runs

To start a kit for runs, click "Prepare Kit" from the run summary. Setting the Current Location of the kit sets the location of the parts in the kit.

A kit will be created that automatically populates the parts required from the Bill of Materials.

![](/files/MbzD6pHPJGaLzh6hdAmH)


# Fulfilling Multiple Kits

To view the status of all kits, requested or otherwise, navigate the Kits view.

From here, kits can be selected to fulfill and the **Kits fulfillment** interface can be used to fulfill multiple kits at once. Setting the Current Location of the kit sets the location of the parts in the kit.

![](/files/KwQCE2h0Hljy2Kqhem5i)

To make updates on a single kit, select the kit number and the side panel will open.

![](/files/MpXHvae5QtBxm42xuKrg)

Kits can also be fulfilled in the side panel view by selecting **Kit inventory**.


# Kanban Kitting

You can use ION to setup a kanban kitting system where you pre-assemble kits into a container in inventory, send it to the production line to be installed, and then send the container back to inventory to pre-assemble the same kit again. This process flow (as shown below) can be helpful for higher volume workflows where the parts required do not change.

<figure><img src="/files/HmLFvhWmzoiIa5h13YuN" alt=""><figcaption></figcaption></figure>

As the rate of installations increases, you can increase the inventory per kit until you reach container limitations. At that point, add more kits to this flow. To minimize production downtime, we recommend trying to maintain a minimum of 2 kits at the lineside location where there is always one kit available for consumption for Technicians while the depleted kit is being re-filled.

To streamline this workflow, ION makes it easy to de-kit all the inventory off a part kit that gets re-used multiple times. Once all the inventory from a kit has been installed and it's time to send the kit back to inventory, have the user click the "Remove all Inventory" button on the Kit page. This will de-kit all the inventory attached to the kit. Then set the status of the kit to Requested as seen in the flow diagram above, and send it back to the warehouse to be refilled.

<figure><img src="/files/gJFfXpoTmAVzFNccrxRI" alt=""><figcaption></figcaption></figure>


# Purchasing

Gain full traceability from purchases into inventory


# Purchase Orders

You can create a Purchase Order from the Purchasing Screen so that you can receive items from external vendors and suppliers. To do so, click the "Purchases" tab. You will see an option to "Place New Order" at the top right, and also two sub-tabs to view your suppliers and receipts. Click on Place New Order.

![](/files/eiUQcH2mTb1gxxXAjh8H)

Enter the supplier you would like to purchase from and click "Create Order".

![](/files/B1p0crJ7MUBrnsPqiTi6)

Add new lines to the purchase order, and select the parts, qtys, costs, and any other information to facilitate the order creation.

![](/files/tAEkwf8CRPPW0TJ7wYOD)

You can print a draft PO at any time, but the watermark will not be removed unless the PO is past the "ordered" state.

When the order has been received, you can continue to processing the `Receiving` and `Inspection` steps.

## Purchase Statuses

The purchase status is determined by the status of all of the line items. Here is the logic of the purchase status in this specific order.

* Draft: If any line item is in Draft, then the purchase is in Draft. In this state, you have the ability to edit the entire purchase order before sending it to review.
* In Review: When any PO line is in a requested state, the purchase is "In Review". In this state, you are going through a review process and ensuring reviewers approve a purchase. Once all reviewers have approved, the purchase moves to Approved.
* Approved: When any PO line is in an approved state, the purchase is Approved. All reviewers have approved and now the buyer can move the purchase to Ordered and send the PDF to the vendor.
* Ordered: When any PO line is Ordered, the purchase is Ordered. If any line items are received, the purchase will still show the Ordered state.
* Received: When any PO line is Received, the purchase is Received. You will only end up in this state if all lines are received or canceled.
* Canceled: If all purchase lines are canceled, then the Purchase is Canceled.

## External Reference

The External Reference on a PO here:

<figure><img src="/files/eulk6gpHid65ccYGWYoV" alt=""><figcaption></figcaption></figure>

Use this box to refer to outside purchase order identifiers like those coming from your ERP system. Example "PO423" from NetSuite will now show up in place of 1075 everywhere that purchase is called out in ION. This value is searchable in the purchase order collections view enabling your team members to use one value when communicating about a purchase order.

### Purchase Templates

You can also use the external reference to create purchase templates that can be copied for common purchases. See below for an example.

{% embed url="<https://www.loom.com/share/6d20821c431e42aaa2e13387807c0e94?sid=bac5b73f-b3d5-4dcf-a9ec-7246f6dafd04>" %}


# Types of Purchases

Purchase any type of good or service through the use of parts and purchases.

## Purchase Types

{% hint style="info" %}
Please reach out to use via Chat if you would like us to turn this on for you.
{% endhint %}

Our customers purchase various goods and services, including inventoried items, physical services like anodizing or heat treatment, software and digital services, office equipment and supplies, capital assets, and more! These can be summed up into three main types of purchase order lines within ION:

* Create Inventory
* Does Not Create Inventory, Physically Received
* Does Not Create Inventory, Digitally Received

### Creates Inventory

For purchases where you need to procure inventoried items, items you need to track, move, install, create issues against, etc., set the part for that purchase to a **Purchase Type** of *Creates inventory.* Use this for all parts that end up on your final product(s). Below is a picture from the [parts](/features/parts-and-trace) screen.

<figure><img src="/files/vGHpbGmt3lctTu5qOVo1" alt=""><figcaption><p>Purchase Type of Creates Inventory</p></figcaption></figure>

These lines will be able to be received, and will automatically generate inventory that is *on order* when you create a purchase order line that calls out that part.

### Does Not Create Inventory, Physically Received

Businesses often procure materials other than manufacturing parts like office furniture, anodizing services, heat treatments, tests, etc. These are items or services that need to be purchased AND received, but are not tracked in inventory and often do not show up on the general ledger. In ERP systems like NetSuite, these are tracked as a separate item type called non-inventory parts. ION now allows you to create, manage, and purchase goods and services that need to be received and do not create inventory in two ways:

<figure><img src="/files/ppRcfiPEXJbPSL2IkACV" alt=""><figcaption><p>You can see here that for the first two lines, both of which do not need inventory, there are no sub-lines, which denotes the lack of inventory.</p></figcaption></figure>

#### For Common Purchases:

Set a part's **Purchase Type** to *Does Not Create Inventory, Physically Received.* This will allow you to quickly purchase that good or service repeatedly, and will ensure when you put the part on a purchase order line, that it will not create inventory.

#### For Uncommon Purchases:

Set a PO line's description only to describe the service. Without a part listed on the PO line, this will function as a non-inventoried purchase line that can be physically received.

<figure><img src="/files/CV0cApSZEFjTclrtRgCF" alt=""><figcaption><p>PO line with no part but has a description defaults to not creating inventory but is physically received.</p></figcaption></figure>

### Does Not Create Inventory, Digitally Received

The last type of purchase line is for purchases where you are not physically receiving anything; therefore, **no ION receipt is required.** A common type of this purchase would be software.

For these, set the part **Purchase Type** to be *Does Not Create Inventory, Digitally Received.*

## Part Setup

#### How do I change the purchase type of a part?

1. Navigate to ION's part library and press Create part.
2. In the create part modal, type in the part information and change the Purchase Type to be one of the following three options as described above. 1.

   ```
   <figure><img src="../../../.gitbook/assets/image (12).png" alt=""><figcaption></figcaption></figure>
   ```
3. Press "Create Part"

**Updating a part:**

You can edit a non-inventory part to make it inventoried so that future purchase orders containing that part will create inventory. The change **WILL NOT** change previously created purchase order lines with that former non-inventory part on it.


# Purchase Order Approvals

Cost based approval thresholds and team/role based approval workflows

{% hint style="info" %}
Please reach out to us via Chat if you would like us to turn this on for you.
{% endhint %}

Using ION's roles and teams, set up and automate approvals at different dollar amount thresholds. When the approval workflow is set up, notifications will be sent to each person in the sequence. Once all the approvals are completed the purchase order will automatically be moved to an approved state. If a purchase order is modified in any way meeting the set threshold for change, setup in organization settings (including increases ***or decreases*** in cost, adjustments to line items, quantities, or pricing) during or after the approval process, the purchase order will require re-approval. Original approvals are only valid if no changes of any kind have been made.

### Organization Purchase Order Approval Policy Setup:

Here is an example of a PO approval policy. An admin can set this up in your organization settings under the purchase order tab. The approvals notifications flow from level 1 to level 4 but anyone can approve at any time.

**Level 1:** For purchase orders the Manager for the team selected on the PO is required to approve the PO

**Level 2:** For purchase orders over $10,000 the Director of the team selected on the PO is required

**Level 3:** For all purchase orders someone on the Finance/Accounting team needs to approve the purchase order

**Level 4:** For POs over $100,000 the CEO is required to approve the PO

<figure><img src="/files/5rnLRx9vsgmElqAbPCZr" alt=""><figcaption></figcaption></figure>

A note on teams and roles:

ION has customizable teams and roles that enable you to model your actual organization structure. For example, if you have an "Electrical Design" team with a team lead and a director you can create a role for team lead and director, assign those roles to users within your organization, and then assign those individuals to that team. In reality, you might have multiple team leads on one team or a team lead can be on multiple teams. This scenario can be modeled as well. If someone goes on vacation an admin can easily add a replacement team member or change someone's role to meet the approval.

### Initiating the workflow on the PO

After setting up the approval policy in org settings you should be able to start approval workflows on PO's.

1. **Buyer:** To initiate the approval workflow, go to the purchase order and press 'Approval Setup'
2. **Buyer:** Once the modal pops up, select the team that this purchase order corresponds with. In this case, the facilities team is required for approval. If submitted at this point, all qualified users for that team and role combination will be notified.

   <figure><img src="/files/UPPaqrzEGa26FzGIWPeW" alt=""><figcaption></figcaption></figure>
3. **Buyer:** Additionally the buyer can specify the particular person whom he/she would like approval from at each step of the process by using the "All Qualifiers" dropdown.
4. **Buyer:** To initialize the workflow press "Submit For Review." The status of the PO should now be "In Review" and a new button should appear at the top of the PO called "Approval Review"
5. **Approvers:** Navigate to the PO or press on the notification you received in your ION notification center. Press "Approval Review" to make your approval. NOTE: By default, all admins can approve any step of the approval sequence

   <figure><img src="/files/17D72IWenlLdq6OZkLcr" alt=""><figcaption></figcaption></figure>
6. In the picture above, there are three approval stages. The first stage is requesting approval from the Manager of the facilities team, which I happen to be. In normal circumstances I would not have access to the second two but because I am an admin I can approve every stage. You see the 20 qualified users because we have 20 admins in our environment. At this point I can approve all levels even though the first level is not approved. The purchase order will not move to Approved until all levels have been approved.

   <figure><img src="/files/o13eGourkZC3wItZvYbk" alt=""><figcaption></figcaption></figure>

When the approval workflow is set on the PO, and the cost thresholds are met then the team lead will be notified first. Once he/she approves the order then the director for that team will be notified. If there are two directors or two team leads then both will be notified but only one will be required to approve.

### Additional Details:

Changing the organization settings while there are active approvals on purchase orders will not affect the existing approval workflows. There will be a reset approvals button to allow you to make these changes live on existing approvals.


# Purchase Order FAQs

This is a list of FAQs for Purchase Orders in ION.

Q: Is it possible to create a purchase item that is not associated with a part or inventory item?

A: Yes, it is possible to create purchase items without parts or inventory. Do this simply by leaving the **Part** field in the purchase empty. See this example:

<figure><img src="/files/666veJ5fn2z4HZupO0zq" alt=""><figcaption></figcaption></figure>


# Supplier Part Numbers & Unit Conversions

[Supplier Part Numbers & Purchase Unit Conversions](/features/parts-and-trace/supplier-part-numbers-and-purchase-unit-conversions)


# PO Requirements, Terms, and Quality Clauses

To add a new PO Line Requirement, go to your suppliers page:

<figure><img src="/files/4ADjJksbTJHWJ2fvy9eQ" alt=""><figcaption></figcaption></figure>

### PO Terms

Click "Requirements" in the top right corner of the page.

<figure><img src="/files/fny1AJvBN0X6Zx1WR4HA" alt=""><figcaption></figcaption></figure>

You'll be taken to a page with your PO Terms, where you can view and edit existing terms, or create new ones. This can be your payment terms and/or terms and conditions of the PO.

### Quality Clauses

In the upper right hand corner of the terms page, you'll also another button for Quality Clauses

<figure><img src="/files/RQUiUoBKtYrdUJkyVH3Q" alt=""><figcaption></figcaption></figure>

Adding Quality Clauses here will allow you to set requirements for each PO line for your vendor to deliver. Some examples of these include Certificate of Conformance, or Dimensional Inspection Reports.


# PO lines editability changes

Changes coming the week of July 28th to simplify the current PO line and PO status experience.

### Why are we making these changes?

To simplify both the buyer's experience and integrations built on top of ION's API, we are making the following changes. Not only does this simplify the experience, but it also makes it more intuitive and easier to navigate cleanly between purchase order states and avoids situations where you get blocked as you need to receive more of a fully received PO line.

### What are the changes?

1. The purchase order line status will now be calculated, and the editability of the PO lines will be tied to the PO status. All properties and attributes in a purchase order line are editable if its corresponding PO is in a `Draft` status, regardless of the status of the PO line.
   * To edit a Purchase Order Line, you will need to change the PO to `Draft` . For all of our customers, you should remain unaffected, as this was a mostly hidden change from the ION application UI.
   * For example, a PO line may be fully received, but we will allow you to increase the quantity of the PO line if the PO is in `Draft`, if you received more than what was written on the PO line.

{% hint style="info" %}
The only PO line attributes that can be edited when the Purchase order is not in a `Draft` status are:

* ETA
* Paid status
* Custom attributes
  {% endhint %}

2. You will no longer have the ability to manually change the Purchase Order Line status to anything outside of `Canceled`. Lines can only be uncanceled when their PO is in `Draft` state.
3. We are deprecating the `Approved` and `Requested` statuses for Purchase Order lines. They will be removed from ION moving forward. The Purchase Order Line will remain in `Draft` until the Purchase Order is placed in an `Ordered` status, then the PO line will be in an `Ordered` status.

{% hint style="danger" %}
There are breaking changes as listed below, please follow these instructions to maintain integrity to any integration you have built with the purchasing module
{% endhint %}

### Actions To Take

If you are:

* Using the PO Line Status of `Approved` or `Requested` or
* Manually updating the PO Line Status to any status that is not `Canceled`.

through the API, webhooks or rules, these will no longer work due to the above changes. The API calls, webhooks, and rules **will need to be updated to use the purchase order object instead.**

{% hint style="info" %}
We strongly recommend using the purchase order status going forward for all webhooks, rules, queries, and mutations.
{% endhint %}

#### For example:

If you use PO Line webhooks and check if the first PO line in a purchase order is `Approved` before creating a purchase order in another system, then this will need to be changed to now check the status in the Purchase Order webhook.

* From: `PURCHASE_ORDER_LINES` Resource and `UPDATE` Action
* To: `PURCHASE_ORDERS` Resource and `UPDATE` Action

### Other API Changes

With these changes, we've cleaned up how editability is returned in our API.

`editable` field is now returned as a Boolean instead of a String field.

*Old:*

```
purchaseOrderLine {
    editable: "true"
}
```

*New:*

```
purchaseOrderLine {
    editable: True
}
```


# Receiving/Inspection

Get your parts from dock to stock with ION Receipts and Inspection runs

## What are Receipts?

Receipts are used to track the event of bringing parts into the factory from outside suppliers. They allow population of key inventory fields such as serial number, lot, and location.

Additionally, receipts can be tied to runs to enable procedural inspections of incoming parts.

### Processing receipts

A receipt is automatically created when moving a PO's state to "Ordered". You can click on "Receive" to go directly to the receipt and process it.

![](/files/tAEkwf8CRPPW0TJ7wYOD)

Here's a short video showing how to do a receipt

{% embed url="<https://www.loom.com/share/445b5471314f4457a8abf9da6012f57f>" %}

If the part being received requires serial tracking (as specified on the part), a serial number will need to be populated before it can be received. The same also applies for lot tracked parts.

Only purchase orders in an **ordered** status can be received. When all parts on a purchase order are received, the purchase order status will be changed to **received** as shown below for the purchase order linked to the above receipt:

![](/files/PdrNlV9AEjPy6bFLMQu3)

### Adding parts to receipts

Additional parts can be added to receipts with the **Receive more parts** button.

![Receive additional parts](/files/-MYhxY-Effu5Cjykbi0T)

### Inspection runs

Procedures now have a type to designate build vs inspection.

![Inspection procedures](/files/-MYhyqsN_AbBgHLCmAKN)

On the part/procedure link, the inspection run can be set as required:

![](/files/-MYi-1GdR1drxZB8AbE4)

Setting this as required and approving the part-procedure relationship will automatically create an inspection run upon receipt for that part number:

![Inspection run automatically created](/files/-MYi0yeKS9i1PqBEVmuf)

#### Receiving non-part purchases (i.e. services)

You can also use receiving to receive purchase items that do not have a part number.

There is little difference to receiving non-parts. The only major difference is that properties that are normally accessible on the inventory such as location, serial number, and lot number are not there because these are not inventory items.

<figure><img src="/files/01HOnvQ5EVqzolbdajNz" alt=""><figcaption></figcaption></figure>

#### Accessing your fully received receipt

Receipts for a PO can be seen by typing the PO number in the search box on the Receipts page:

<figure><img src="/files/VSmtWn0BxLW8ebsFw6EY" alt=""><figcaption></figcaption></figure>


# Outside Processing

Outside Processing is now enabled in ION.

Many parts require a process, such as anodization or heat treatment, which may happen out of house. With ION's new outside processing functionality you can now mark your procedure steps as Outside Processing steps and send the part & the process out on a purchase order.

<figure><img src="/files/3CwfGE1haTQ3h0Gy77Ma" alt=""><figcaption></figcaption></figure>

After marking a step as an "outside process" in a procedure, creating a run will show you some options for using the outside processing feature. If not in Beta, you'll see a screen like below. Clicking "here" will take you to the Runs Beta and show you the outside process options.

<figure><img src="/files/cPmf2AN3yHGgI0bGmaTb" alt=""><figcaption></figcaption></figure>

Once in the beta view, you can select a purchase order or or create a new purchase order to perform the outside process on.

<figure><img src="/files/NkjXiY4qjD7dt9fGMekw" alt=""><figcaption></figcaption></figure>

Clicking "Create New Purchase Order" will automatically link it to the run. You'll also be able to see the live status of the PO in the same box.

<figure><img src="/files/zzDk4SvbPczWwYooWlXZ" alt=""><figcaption></figcaption></figure>

Clicking the purchase order will navigate to the PO screen. The description of the PO line will tell you the source of that PO line.

<figure><img src="/files/v2uIUq22lVr6AGWuYLCc" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Run steps flagged as Outside Process will not be batched
{% endhint %}

### Adding an outside process step on the fly:

If you decide that an existing run requires an outside process you can add in an outside process step via redline. *This functionality is only available via the beta runs view.*

1. Go to the step in the run that you would like to add an outside process step after
2. Put the step in redline and add a step
3. In the new step creation screen, type in your step name and click the "Is Outsourcing Process" boolean to true. You can also select an existing outside process step or standard step
4. Press save.

   <figure><img src="/files/uowirTAp8Wz4KHw5Np7h" alt=""><figcaption></figcaption></figure>


# Consigned Parts

A consigned part refers to a component or material that is provided by one party (typically the customer or buyer) to another party (often a manufacturer, supplier, or contract assembler) for use in a manufacturing or assembly process. In this arrangement, ownership of the part remains with the consigning party (the customer) until it is used or consumed in production.

In ION, we can tie together, Purchases, Runs, and Kits to ensure your vendors receive the consigned parts and they are installed on to the aBOM of your assembly once received. Check out the flow below on the details of the process.

1. Create a Purchase Order
2. Create a Run
3. Create a Kit tied to the run
4. Kit the inventory needed and deliver the kit to the vendor. Mark the corresponding steps as completed. For more granularity, tie a location to the kit that represents a vendor. This will ensure that when looking in inventory, that it will show as the vendor's location.
5. Tie the PO line to the Run Step using an [Outside Processing](/features/purchasing/outside-processing)step!
6. Once the assembly is received, complete the receiving inspection step.
7. Install the consigned parts into the aBOM using the Install from Kit button. Complete the run!

<figure><img src="/files/TvBODqkeecbkFTcBiRbH" alt=""><figcaption></figcaption></figure>


# Barcode Labels

Speed up your ION workflows with barcodes! ION includes workflows for templating, printing, and scanning labels to reduce clicks and increase reliability in your process.

![](/files/ZJnj6y9FPXKmCE4XVVtS)


# Templating

Within organization settings, barcode label templates can be defined for inventory, runs, or locations.

<figure><img src="/files/CJHDe0fzhwnVqIlkPFI0" alt=""><figcaption></figcaption></figure>

Many templates can be defined per a type of object (i.e. inventory). This is handy for differing purposes - you might have a shipping label that is different from the one that is used for internal part movement. Or maybe you have a really small barcode label with just a barcode that gets used for smaller parts.

The template uses ZPL(Zebra Programming Language), which is the language of Zebra printers and is also used by other printers as well. This may look difficult to understand, but it's quite easy to get a hang of the basics for creating new labels. There is also an open source service named [Labelary](http://labelary.com/viewer.html) that can be used to render your templates to get the sizing and spacing correct.

Templates use variables specified with a syntax that looks like this: `${serialNumber}`. These are used to inject variables into the label template. A full list of variables available are shown to the left of the template in ion.

NOTE: Some variables reference values on the object that are calculated. For example, **earliestRunId** is available when creating a barcode label for a part inventory, and provides the id for the first created run associated with that inventory. If the inventory has been split (one or more times) since its creation, earliestRunId will reference the first created run of the original inventory from which it was originally split.

An example of a label template is shown below:

![](/files/QYfoRJdg94PLCxUgzWLL)

During the print process, when data is injected, the actual label will looks something like:

![](/files/QGQaIWML08VWNfWSvEuV)

#### Template Option: `earliestRunId`

The earliestRunId property is available when generating barcode labels for part inventories. This property provides a direct reference to the first run associated with that inventory, ensuring consistent traceability from the point of origin.

* Primary Runs: If the inventory has one or more runs directly linked to it, `earliestRunId` is set to the run created first (based on creation date).
* Split Inventories: If the inventory has been split one or more times, `earliestRunId` will reference the first run from the original inventory, again based on creation date.


# ION barcode minimum sizes

Using the magnification factor on the barcode in ZPL you can generate a very small label. ION barcodes contain a json with a uid (Universal Identification) string by default that looks like this:

```
{"uid":"24daeec708d84908af9beba707a5241b"}
```

[Here's an example](http://labelary.com/viewer.html?density=12\&quality=grayscale\&width=.25\&height=.25\&units=inches\&index=0\&rotation=0\&zpl=%5EXA%0A%5EFO20%2C15%5EBQN%2C2%2C1%5EFD%7B%22uid%22%3A%2224daeec708d84908af9beba707a5241b%22%7D%5EFS%0A%5EXZ%0A) of a very small QR code (magnification of 1) that contains an ION uid. This is on a .25x.25 label size with a 300 dpi printer and there is plenty of room to spare. The basic scanner that we are using to test was still able to scan this without issue.

![](/files/Otou7WrU4C5jPSXleIWz)


# Sample templates

Here's an example of a few basic templates created with a barcode and text:

{% tabs %}
{% tab title="Inventory Labels" %}
{% code title="1x1 Inventory Label" overflow="wrap" %}

```
^XA
^PW211^FO55,30^BQN,2,3^FDQA,S1033^FS
^FT0,170^A0,30^FB211,1,0,C,0^FH\^FDPN:${part.partNumber}^FS
^XZ
```

{% endcode %}

{% code title="3x1 Inventory Label" overflow="wrap" %}

```
^XA

Logo:
^FO520,35^GFA,2470,2470,13,Q01F8,Q0IF,P07IFE,O01KF8,O03KFC,O0MF,N01MF8,N03MFC,:N07MFE,N0OF,:M01OF8,:M03OFC,::::M07OFE,::::M03OFC,:::M01OF8,:N0OF,:N07MFE,:N03MFC,N01MF8,O0MF,O07KFE,O01KF8,P0KF,P01IF8,Q03FC,,::::::::::::N0IFE07IF,O0306001C3,O0106I083,::O0306I083,O0706I083,O0F06I083,N0398CJ03,N070FC,N0C078,,S07IF,,N0IFE,N0E38E,N0C106,N0C10607IF,:N0C106I083,:::T0183,T0783,T0EC3,N03830038E6,N070FC0707C,N040CC,N0C186,:N0C10601C3C,N0C1060307E,N0C30602043,N0430C060C3,N07E1C060C3,N03C1006083,S06083,S06183,O07C00318E,N01FF003F0C,N0301800E,N0600C,N0C004J03,N0C006J03,:::N0C00407IF,N0600C03IF,N03838J03,N01FFK03,O038K03,V03,,:N0IFE,P01E,P018,P07,O01C,O038,O0E,N01C,N07,N0F,N0IFE,,::N0E,N07C,O0F8,O0DE,O087C,O081E,:O08F8,O0FC,N01F,N078,N0C,,:N0IFC,N0IFE,P01C,P038,P0F,O01C,O07,O0E,N038,N07,N0IFE,:,::O0FE,N03FF8,N0701C,N0600C,N0C006,::::N0600C,N0701C,N03818,,::N0IFC,N0IFE,N0C106,:::::::,::::::::::^FS

^PW576^FO12,75^BQN,2,3^FDQA,S1033^FS
^FO12,35^A0,45^FD${part.partNumber}^FS
^FO130,85^A0,32^FDRev: ${part.revision}^FS
^FO130,125^A0,25^FD${part.description}^FS
^FO130,155^A0,25^FDSN: ${serialNumber}^FS
^FO330,155^A0,25^FDLot: ${lotNumber}^FS
^XZ
```

{% endcode %}

{% code title="3x1 Logo Label" overflow="wrap" %}

```
^XA
^PW576
^CFA,15
^FX Company Logo
^FO0,2
^GFA,2470,2470,13,Q01F8,Q0IF,P07IFE,O01KF8,O03KFC,O0MF,N01MF8,N03MFC,:N07MFE,N0OF,:M01OF8,:M03OFC,::::M07OFE,::::M03OFC,:::M01OF8,:N0OF,:N07MFE,:N03MFC,N01MF8,O0MF,O07KFE,O01KF8,P0KF,P01IF8,Q03FC,,::::::::::::N0IFE07IF,O0306001C3,O0106I083,::O0306I083,O0706I083,O0F06I083,N0398CJ03,N070FC,N0C078,,S07IF,,N0IFE,N0E38E,N0C106,N0C10607IF,:N0C106I083,:::T0183,T0783,T0EC3,N03830038E6,N070FC0707C,N040CC,N0C186,:N0C10601C3C,N0C1060307E,N0C30602043,N0430C060C3,N07E1C060C3,N03C1006083,S06083,S06183,O07C00318E,N01FF003F0C,N0301800E,N0600C,N0C004J03,N0C006J03,:::N0C00407IF,N0600C03IF,N03838J03,N01FFK03,O038K03,V03,,:N0IFE,P01E,P018,P07,O01C,O038,O0E,N01C,N07,N0F,N0IFE,,::N0E,N07C,O0F8,O0DE,O087C,O081E,:O08F8,O0FC,N01F,N078,N0C,,:N0IFC,N0IFE,P01C,P038,P0F,O01C,O07,O0E,N038,N07,N0IFE,:,::O0FE,N03FF8,N0701C,N0600C,N0C006,::::N0600C,N0701C,N03818,,::N0IFC,N0IFE,N0C106,:::::::,::::::::::^FS
^FX Text Part Detail Section
^FO 80,2  ^FD ${part.description} ^FS
^FO 80,22  ^FD P/N: ${part.partNumber} ^FS
^FO 80,47  ^FD UOM: ${unitOfMeasure.type} ^FS
^FO 80,72  ^FD PO: ^FS
^FO 80,97 ^FD S/N: ${serialNumber} ^FS
^FO 80,122 ^FD Lot: ${lotNumber} ^FS
^FO 80,147  ^FD Custom Attribute: XX"^FS
^FO 80,172 ^FD Custom Attribute: XX^FS
^FX Status and Part Revision
^FO 380,20^GB50,50,6^FS
^FO 380,38 ^FD XX^FS
^FO 380,75^GB50,50,3^FS
^FO 380,85 ^FD Rev^FS
^FO 380,105 ^FD ${part.revision}^FS
^FX QR Code
^FO 450,20 ^BQN,2,3,Q,7 ^FDQA,${iuid}^FS
^FO 380, 135 ^FD Qty: ${quantity} ^FS
^FO 380, 155 ^FD UID: ${id} ^FS
^XZ
```

{% endcode %}

<div><img src="/files/72nSPGk0BAG0tWOIWYpl" alt="1x1 Inventory Label Render"> <figure><img src="/files/ytbQhwhJeWeLzYlZD2wn" alt=""><figcaption><p>3x1 Inventory Label Render</p></figcaption></figure></div>

<img src="/files/K3XU1eUrjGMPRrYduyov" alt="" data-size="original">
{% endtab %}

{% tab title="Kit Labels" %}
{% code title="1x1 Kit Label" overflow="wrap" %}

```
^XA
^PW211^FO55,30^BQN,2,3^FDQA,S1033^FS
^FT0,170^A0,30^FB211,1,0,C,0^FH^FDKit #:${id}^FS
^XZ
```

{% endcode %}

{% code title="3x1 Kit Label" overflow="wrap" %}

```
^XA

Logo:
^FO520,35^GFA,2470,2470,13,Q01F8,Q0IF,P07IFE,O01KF8,O03KFC,O0MF,N01MF8,N03MFC,:N07MFE,N0OF,:M01OF8,:M03OFC,::::M07OFE,::::M03OFC,:::M01OF8,:N0OF,:N07MFE,:N03MFC,N01MF8,O0MF,O07KFE,O01KF8,P0KF,P01IF8,Q03FC,,::::::::::::N0IFE07IF,O0306001C3,O0106I083,::O0306I083,O0706I083,O0F06I083,N0398CJ03,N070FC,N0C078,,S07IF,,N0IFE,N0E38E,N0C106,N0C10607IF,:N0C106I083,:::T0183,T0783,T0EC3,N03830038E6,N070FC0707C,N040CC,N0C186,:N0C10601C3C,N0C1060307E,N0C30602043,N0430C060C3,N07E1C060C3,N03C1006083,S06083,S06183,O07C00318E,N01FF003F0C,N0301800E,N0600C,N0C004J03,N0C006J03,:::N0C00407IF,N0600C03IF,N03838J03,N01FFK03,O038K03,V03,,:N0IFE,P01E,P018,P07,O01C,O038,O0E,N01C,N07,N0F,N0IFE,,::N0E,N07C,O0F8,O0DE,O087C,O081E,:O08F8,O0FC,N01F,N078,N0C,,:N0IFC,N0IFE,P01C,P038,P0F,O01C,O07,O0E,N038,N07,N0IFE,:,::O0FE,N03FF8,N0701C,N0600C,N0C006,::::N0600C,N0701C,N03818,,::N0IFC,N0IFE,N0C106,:::::::,::::::::::^FS


^PW576^FO12,105^BQN,2,2^FDQA,S1033^FS
^FO12,35^A0,45^FDKit #: ${id}^FS
^FO330,35^A0,45^FDRUN-${runId}^FS
^FO12,85^A0,25^FD${run.title}^FS
^FO100,125^A0,25^FDCreated By: ${createdBy.name}^FS
^FO100,155^A0,25^FDDeliver To: ${deliveryLocation.name}^FS

^XZ
```

{% endcode %}

<div><figure><img src="/files/io8k6MQK5p3WfwjXi3eL" alt=""><figcaption><p>1x1 Kit Label Render</p></figcaption></figure> <figure><img src="/files/rJVxSkFctzkmUCKp7X7M" alt=""><figcaption><p>3x1 Kit Label Render</p></figcaption></figure></div>
{% endtab %}

{% tab title="Location Labels" %}
{% code title="1x1 Location Label" overflow="wrap" %}

```
^XA
^PW211^FO55,30^BQN,2,3^FDQA,S1033^FS
^FT0,170^A0,30^FB211,1,0,C,0^FH^FD${name}^FS
^XZ
```

{% endcode %}

{% code title="3x1 Location Label" overflow="wrap" %}

```
^XA

Logo:
^FO520,35^GFA,2470,2470,13,Q01F8,Q0IF,P07IFE,O01KF8,O03KFC,O0MF,N01MF8,N03MFC,:N07MFE,N0OF,:M01OF8,:M03OFC,::::M07OFE,::::M03OFC,:::M01OF8,:N0OF,:N07MFE,:N03MFC,N01MF8,O0MF,O07KFE,O01KF8,P0KF,P01IF8,Q03FC,,::::::::::::N0IFE07IF,O0306001C3,O0106I083,::O0306I083,O0706I083,O0F06I083,N0398CJ03,N070FC,N0C078,,S07IF,,N0IFE,N0E38E,N0C106,N0C10607IF,:N0C106I083,:::T0183,T0783,T0EC3,N03830038E6,N070FC0707C,N040CC,N0C186,:N0C10601C3C,N0C1060307E,N0C30602043,N0430C060C3,N07E1C060C3,N03C1006083,S06083,S06183,O07C00318E,N01FF003F0C,N0301800E,N0600C,N0C004J03,N0C006J03,:::N0C00407IF,N0600C03IF,N03838J03,N01FFK03,O038K03,V03,,:N0IFE,P01E,P018,P07,O01C,O038,O0E,N01C,N07,N0F,N0IFE,,::N0E,N07C,O0F8,O0DE,O087C,O081E,:O08F8,O0FC,N01F,N078,N0C,,:N0IFC,N0IFE,P01C,P038,P0F,O01C,O07,O0E,N038,N07,N0IFE,:,::O0FE,N03FF8,N0701C,N0600C,N0C006,::::N0600C,N0701C,N03818,,::N0IFC,N0IFE,N0C106,:::::::,::::::::::^FS



^PW576^FO12,25^BQN,2,3^FDQA,S1033^FS

^FO120,35^A0,45^FD${locationSubtype.name}: ${name}^FS
^FO120,85^A0,25^FD${parent.type}: ${parent.name}^FS
^FO120,115^A0,25^FD ${address}^FS
 

^XZ
```

{% endcode %}

<div><figure><img src="/files/rvAiPHklDX5MiBsf4Fxi" alt=""><figcaption><p>1x1 Location Label Render</p></figcaption></figure> <figure><img src="/files/9gPCyZ3Kvb3QfZjj3dnr" alt=""><figcaption><p>3x1 Location Label Render</p></figcaption></figure></div>
{% endtab %}
{% endtabs %}

You can use [Labelary](http://labelary.com/) to add an image for your logo (or any other image you'd like to add) using this website. The image gets encoded as a Base64 string. See here for this example.

You can get a better understanding of the code by checking out this [programming guide](https://www.zebra.com/content/dam/zebra_new_ia/en-us/manuals/printers/common/programming/zpl-zbi2-pm-en.pdf)!

**Note**: For the QR code on line 3 of the above template, it includes "QA,". This is added to ensure all characters show up in the barcode as outlined [here](https://www.zebra.com/us/en/support-downloads/knowledge-articles/ait/QR-code-missing-first-three-characters-when-using-ZPL-language.html).


# Printing

Inventory, location, and other screens now include an option to print barcodes as shown below.

![](/files/KGWfqXxXcp8YvS8GCrPn)

In addition, a QR code and full label is rendered in the print modal as a preview.

### Printer requirements

Not all printers will work with ION's v1 implementation. We require printers to do be able to do 2 things:

1. Connect to the internet(wifi or ethernet)
2. Work with middleware named [**Zebra Browser Print**](https://www.zebra.com/us/en/support-downloads/software/printer-software/browser-print.html)**. This has to be downloaded** on each users computer to enable printing. ION communicates with this desktop application, which then in turn communicates with the printers.

#### Printers that work with ION

The Zebra brand Printers generally work with Zebra Browser Print and therefore ION. You should order one of those printers to print barcodes with ION.

## Troubleshooting

If you get an error message that looks like this:

<figure><img src="/files/FbBW04Xl2MC0Fci5vHWq" alt=""><figcaption></figcaption></figure>

If means you have the "Use Print Server" button checked, but you don't have an API key set in your organizational settings. Please check that you meant to enable the print server feature, and either fill in the API key or uncheck the box.


# Configuring Zebra Browser Print

Instructions on how to download Zebra Browser Print and use with ION.

1. Download Zebra Browser Print [from here](https://developer.zebra.com/products/printers/browser-print) (available for both PCs and Macs)
2. Follow these [instructions here](https://supportcommunity.zebra.com/s/article/Installing-Zebra-Browser-Print-for-Mac?language=en_US) (for Mac, but virtually the same for PC)
3. Select a default printer in the Browser Print settings

![](/files/4qHWW9sPElpjsWlcSayr)

4\. Open the barcode modal in ION and select a printer (these should populate from the Zebra app). If you haven't already created a template, follow the steps [here](https://manual.firstresonance.io/features/barcode-labels/templating).

![](/files/o4f8dR7etYt2VnNgG9O1)

### Troubleshooting

1. Make sure your computer and printer are connected to the same network. The browser will only be able to access printers on the same network
2. If the printers don't appear in the ION print barcode modal, but display in the Zebra Browser Print application, try going to <https://localhost:9101/available>. You might need to authorize the browser to connect with Zebra Browser Print. You'll see a button appear for this link when no printers appear to make it easier to navigate there.

![](/files/8hr7VzywTEahTBipT1Y7)

2\. If your printers show up in the ION print modal dropdown, but you get an error when trying to print, try the following steps. We've seen some issues with printing to the default printer with Zebra Browser Print for some folks.

* add the printer manually in Zebra Browser Printer under a different name
* don't make it the default
* select the printer that you just added in the dropdown when printing

![](/files/YZhuJ1yV9HRI4lOGNaUI)


# Server Based Barcode Printing (PrintNode)

## Overview

Server printing connects the ION app to your printers via an online service called PrintNode. Advantages include the following:

* *Simplified Configuration:* PrintNode allows administrators to manage printer settings and configurations from a central server, reducing the need for individual client setups and thereby reducing the time it takes individuals to start printing barcodes.
* *Effortless Expansion:* Adding new printers or users is straightforward, as configurations are managed server-side, facilitating growth without significant client-side changes.
* *Consistent Updates:* Updates and maintenance can be applied centrally, ensuring all connected printers operate with the latest configurations.

This process requires configuring your printers, creating a PrintNode account, installing the PrintNode client, and entering an API key in your Org settings. You only need to set up the PrintNode client on the computer that will manage the printers once. If you prefer, you can also install the client on multiple computers to manage different parts of your printer fleet.

{% hint style="info" %}
Please contact your First Resonance Customer Success manager or email <support@firstresonance.io> for details on activating the server printing option. You will not have access to this part of the setup until the First Resonance team has activated that option for you.
{% endhint %}

{% hint style="info" %}
Please note that PrintNode is not a service sold or managed by First Resonance.
{% endhint %}

{% hint style="info" %}
The integration available through the ION Marketplace is intended for non-ITAR use only. ITAR-regulated customers may use this integration solely upon acknowledging that no ITAR-controlled data will be transmitted, stored, or printed, including on barcode labels. First Resonance assumes no responsibility for any unauthorized inclusion or handling of ITAR-controlled information.
{% endhint %}

## Steps to Set Up

#### 1. Create a PrintNode Account

* Sign up at [PrintNode](https://www.printnode.com/).
* Start with a one-month free trial. A payment plan is available if you add your card.

#### 2. Install PrintNode Client

* Download and install the client on the machine that will manage the printers.
* Installation guides for different operating systems:
  * [Windows](https://www.printnode.com/en/docs/installation#windows)
  * [Mac](https://www.printnode.com/en/docs/installation#mac)
* When running the client, you should see the list of printers under the printers tab.

#### 3. Set Up Printers

Ensure to set up printers on the computer that will run the PrintNode client.

#### Internet Connection:

* Obtain the printer's IP address by holding the feed and cancel buttons on the printer for 2 seconds and examining what’s printed out.

#### Windows Users:

* Follow this [Windows guide ](https://supportcommunity.zebra.com/s/article/Adding-a-networked-Zebra-Printer-to-a-Windows-10-PC?language=en_US)to set up the printer over the network.

#### macOS Users:

* Follow the [macOS guide](https://www.printnode.com/en/docs/raw-printing-for-osx) to set up the printer. Ensure the printer is set as **RAW**, not Zebra.
* Note: The guide assumes a USB connection. For step 5, choose **Internet Printing Protocol** within Other Network Printers instead:

<figure><img src="/files/T8Qn85hybPGTkaNurRzt" alt=""><figcaption></figcaption></figure>

* Input the IP address in the format `ipp://<printer-ip>/ipp/print` e.g. `ipp://192.168.1.111/ipp/print`
* Follow the rest of the guide, ensuring to select **RAW** for the Make, not **Zebra**.

#### 5. Obtain API Key

* Go to your API keys page, log in, and find your API key.

<figure><img src="/files/CyWGjaSkP3r8ce3GrTuj" alt=""><figcaption></figcaption></figure>

#### 6. Configure ION App

* Navigate to **Organization** in the sidebar.

<figure><img src="/files/flK6BRRIDbE8730xwADt" alt=""><figcaption></figcaption></figure>

* Scroll down to the Barcode Labels section.
* Check "Use Print Server" and enter your PrintNode API key.

Once these steps are completed, server-based printing will be enabled in your ION app across all pages.


# Scanning

Scanning workflows are built into ion to perform actions much quicker than mouse + keyboard.

### How Scanning Works

ION determines a barcode has been scanned by listening for characters being typed in quickly that match the ION ID specification. Based on the scanned object, ION allows you to take quick actions, like moving a bin or installing a component.

When scanning a barcode in ION, ensure that an ION window is open and focused in the browser and scan with a barcode scanner connected to your computer.

Scanning is enabled on all screens in ION.

### Recommended Scanners

Since ION recognizes barcodes by looking for quickly typed-in characters, any barcode scanner that connects to your computer using the [HID specification](https://docs.microsoft.com/en-us/windows-hardware/drivers/hid/) should work with ION. In general, most USB and bluetooth scanners should work. We recommend the [NADAMOO Wireless QR code scanner](https://www.amazon.com/dp/B06Y2RMM51?ref=ppx_yo2_dt_b_product_details\&th=1) for for testing barcodes.

### Workflows

There are 3 types of objects that can be scanned in ION: `inventory`, `locations`, and `kits`.

When scanning one of these objects, you will first see an indication that a scan has occurred.

<figure><img src="/files/23kEj9laYuma6Ece0Psc" alt=""><figcaption></figcaption></figure>

Once the object data loads, you are presented with a list of options. **Note**: You do not need to wait until the data loads to take the next action. These options may require either an additional scan or a click.

For instance, if you scan an `inventory` and then scan a `location`, the inventory will be moved to that location. See below for the system diagram of scan actions (**note**: tools are a type of part inventory. All actions for inventory below apply also to tools).

<figure><img src="/files/wzVUmWMjHYciuLaSkQLH" alt=""><figcaption></figcaption></figure>

#### Installing Inventory

This is the one scan workflow in ION that requires the user to be on a specific page. When scanning a part inventory on the Run execution view, it will try to install that part (if the part is on the aBOM).

![](https://lh5.googleusercontent.com/8G_I3j9sUmZKwlGCSx0nHniLDGSOJocJDtuelyAocTcVD_GtPI4lAa8Lanwi1lDWWLq1f_08ruBF-gj2_ROrXTRIjrW39QZjmw4ac8Eo8l028V1s8bqH1F0TMI7HAzSXmdFEt0iiQEA)

### Example workflows

Below show several examples of scan workflows available in ION.

| ION workfow               | Scans required                                                                                                                                                                                         | Notes                                                                                                                                   |
| ------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | --------------------------------------------------------------------------------------------------------------------------------------- |
| Move inventory            | scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">location</mark>                                                                                                     |                                                                                                                                         |
| Move multiple inventories | scan <mark style="color:yellow;">location</mark> scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">inventory</mark> | All 3 inventories would be moved to the new location.                                                                                   |
| Kit inventory             | scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">kit</mark>                                                                                                          |                                                                                                                                         |
| Kit multiple inventories  | scan <mark style="color:yellow;">kit</mark> scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">inventory</mark> scan <mark style="color:yellow;">inventory</mark>      | All 3 inventories would be kitted                                                                                                       |
| Move location (totes)     | scan <mark style="color:yellow;">location</mark> scan <mark style="color:yellow;">parent location</mark>                                                                                               |                                                                                                                                         |
| Install part              | scan <mark style="color:yellow;">inventory</mark>                                                                                                                                                      | Only works on run execution screen. Also, works for substitutes. If the part is lot-tracked, the quantity must be confirmed by the user |

#### Scan Inventory and Navigate to Open Runs

When scanning an inventory anywhere in ION, you will see a toast that looks like the image below. You can use these toasts to navigate to open runs quickly. This is very useful for a physical queue-based system where you have an incoming rack that you can scan, navigate to the operation, complete the operation, and move the part to the outgoing rack. Examples of where this may be useful are in receiving inspection labs, in NDE labs (X-Ray, Ultrasonic, etc.), or for assembly line work.

{% embed url="<https://www.loom.com/share/df6088099d9748fc86244bdb86aa3e9a>" %}
Scan an inventory barcode to quickly navigate to its run(s)
{% endembed %}

<figure><img src="/files/0nKQe46nnKNiSVkMMDHQ" alt="" width="512"><figcaption></figcaption></figure>


# Scan barcodes from other systems

Define custom barcode patterns so that ION can understand barcodes from other systems

By default, ION expects a specific format for internally defined barcodes, but you can also scan barcodes from other systems with some basic configuration.

This can only be setup through the API currently. Let's use the below example to explain how to setup ION.

#### Example

In this example, you have an inventory barcode from another system that follows a pattern similar to a [GS1 barcode](https://www.gs1.org/standards/barcodes/databar).

That pattern looks like:

```
(01)<Part number>(17)(10)<Serial number>
```

ION uses [Regular expressions (RegEx)](https://en.wikipedia.org/wiki/Regular_expression), the standard for string pattern matching in software, to define the barcode pattern.

Converting this to a regular expression, the pattern for this example would be:

```
\(01\)(?P<part_partNumber>.*)\(17\)\(10\)(?P<serialNumber>.*)
```

This [RegEx website](https://regex101.com/) can be used for testing. The below snippet shows how you can validate your pattern with test barcode text.

Now that the pattern is defined, it's time to input it into ION. Use the GraphQL explorer in ION to add the pattern via the API.

<figure><img src="/files/fCuAG50gHlCvym2qgJEO" alt=""><figcaption></figcaption></figure>

**Note**: If you have included escape characters in your RegEx pattern, make sure to include a second `\` when inputting the expression into the API. These should show as double back slashes `\\`. This is necessary to meet JSON input requirements.

Here's the mutation in text if you'd like to copy from this example.

```
mutation CreateBarcodePattern($input: CreateBarcodePatternInput!) {
    createBarcodePattern(input: $input) {
        barcodePattern {
          id
          _etag
          entityType
          expression
        }
    }
}
```

```
{
  "input": {
    "entityType": "PARTS_INVENTORY",
    "expression": "\\(01\\)(?P<part_partNumber>.*)\\(17\\)\\(10\\)(?P<serialNumber>.*)"
  }
}
```

You can also use the below query to find all barcode templates that exist in your company's ION instance.

```
{
  barcodePatterns {
    edges {
      node {
        expression
        entityType
        id
        _etag
      }
    }
  }
}

```

After you execute the mutation, your company can scan barcodes from other systems and ION will find the correct corresponding object. To test out this functionality before implementing it in production, create test QR codes with a website like [Cognex](https://www.cognex.com/resources/interactive-tools/free-barcode-generator) or [QR-Code-Generator](https://www.qr-code-generator.com/).

Check out the below snippet that finds the appropriate inventory with part number `EX-PART-001` and serial number `1` from a scan.

<figure><img src="/files/G1UybqFoxX5ma9xRopNO" alt=""><figcaption></figcaption></figure>

If the barcode scan is matched by multiple items in ION, the user will be presented with a list of options to choose from. Below shows a scan that matches 2 inventory items sharing the same part number/lot number combination.

<figure><img src="/files/m51WQM88l533JVg80v5r" alt=""><figcaption></figcaption></figure>


# Quality

The most critical aspect to all manufacturing operations.

Quality in ION exists throughout the platform. From traceability of an aBOM, inventory transaction history, review requests on redlines, and issues; these all play a pivotal part in ensuring you and your customers know exactly what happened on the production floor and why.

### Critical quality components talked about here and elsewhere in this manual:

* [Further Actions (CAPA)](/features/quality/further-actions-capa)
* [Issues](/features/quality/issues)
* [Redlines](/features/runs/redlining)
* [Tools](/features/tools)


# Issues

Capture non-conformances on your production floor.

As part of our Factory OS, ION leverage its **Issues** module to provide quality management while being tightly integrated into production. With Issues, manufacturers can:

* Capture data about problems in hardware builds
* Isolate nonconforming parts and prevent quality escapes
* Track and enforce decisions made the Material Review Board
* Trace material through complicated repair and Return Merchandise Authorization processes
* Identify opportunities for process improvement
* Assign team members to drive issues and their associated dispositions

### Issue Functionality

{% @storylane/embed %}

### Issue Creation

{% @storylane/embed %}

**Issue Creation Fields**

* Inventory: Attach the inventory associated with the issue.
* Destination: Select a destination in which to move the inventory. An example use case is moving this inventory to an MRB location until issue resolution occurs.
* Text fields: Document what happened and what was expected to happen.
* [Attributes](/features/custom-attributes): Populate attributes relevant to this issue.

## Areas Of the Issue Ticket:

### Main Body Content

* Fields in main body accept images
* Auto-expansion as information is filed out in these fields
* The fields show saved status. To save click out of the main body and verify with the "Saved" status.
* Alias these fields to customize the title of each section, do so through your Issues organization settings.

<figure><img src="/files/RkMAq6TLoZapszXfAzbX" alt=""><figcaption><p>Old vs. New Rich text input fields</p></figcaption></figure>

#### Value

This enables the user to view long form paragraphs that are often a result of disposition or issue descriptions. Viewing all the content at once time allows people to connect the dots and better ideate on solutions to the issue at hand. The save status finally will ensure that your hard work is not lost when interacting with these fields. It will also help facilitate printing of the issues page as information will not be hidden in scrolling viewports.

### Content Side Bar

* Greater accessibility to the items related to the issue ticket.
* File preview when you click on attachments
* Side rail selection is made obvious through color change
* Hide the rail to support a clean containerized look for editing main body fields.

<figure><img src="/files/N8KVFfvtm9r7NkWBhUMG" alt=""><figcaption><p>Side Bar Opened Up Next To Main Content</p></figcaption></figure>

#### Value

The side bar plays nicely into the container styling the the issues page inherits. Quick access to items within the side bar allow for quicker referencing of those items within main body text. It also allows for a minimized scrolling experience on the screen.

### Approvals Modal

* Approvals Modal Flow Indication
  * Steps for approval more apparent (Disposition and Resolution)
  * Movement through those steps made obvious
  * Clear indications of when you can and cannot do things
  * Status tool tips in the overflow menu of why states are accessible/ inaccessible at times
  * Approvals accessible without scrolling to the bottom of the history.

<figure><img src="/files/gYkiiE99FZHYee7nKL1H" alt="" width="375"><figcaption></figcaption></figure>

#### Value

The modal surfacing what approval gate you are trying to pass through will inherently improve flow through the most streamlined process. This new flow also decreases the number of clicks needed to move an issue through its various states. Buttons from within the modal and better logic automatically update the issue's status. Tool tips give insight into why the ticket can or cannot be moves through different [states](/features/quality/issues-states-dispositions-and-resolutions) decreasing user frustration and guiding what the expected next steps are.

### Redlines

* [See here for overarching redlines functionality and best practices.](/features/runs/redlining)
* Create redlines directly from the issues page in the redlines menu run step picker.
  * Adding a run step that is in TO DO here will move that step into redline.
  * Adding a run step that is in REDLINE will associate that redline with this issue ticket.
    * NOTE: Redlines that are already associated with another issue will not show up here as they are critical to solving that "other" issue. If you do need to change the association, you can do so from the run itself.
* Redlines show all prior approved redlines associated with the issue as well as the open redlines on the issue. (Previous version only showed open redlines and did not include redline ID)
* When passing through approval gates, any open redlines get approved as part of the issue approvals process! This feature has always been there, this is merely a reminder of such.

<figure><img src="/files/7MGfkHmfySv8YYOxsAqU" alt="" width="314"><figcaption><p>Redlines Associated with the Issue</p></figcaption></figure>

{% hint style="info" %}
When an issue is moved from **Pending** to **In Progress**, any redlines linked to the issue will be released
{% endhint %}

### Header

* Better understand the progress being made on the issue by the Issue Status bar.
  * Move between statuses if you desire using the arrows at the end of bar.
    * Movement is dictated by the state you are in plus the disposition and approvals statuses.

<figure><img src="/files/PjLnobPLrTzyxztSz8o6" alt=""><figcaption><p>Header Better Indicates Progression of the Ticket</p></figcaption></figure>

### Comments

* Comments are now always surfaced on the front page.
* This brings them out of the approvals and sidebars menu to increase collaboration and visibility.
* The activity feed creates a in-line comments view with approvals and rejections so that context is conveyed with the comment.

<figure><img src="/files/IzSpeSg1Dmp63icrbr2S" alt=""><figcaption><p>In-line comments activity feed at the bottom of the issues page.</p></figcaption></figure>

### Issues On Inventory

Inventory can be linked to issues to indicate manufacturing errors, damage, or other problems.

Inventory can be linked to issues in the following ways:

* Issues can be created directly from Inventory from the Inventory and Purchases menus
* If an issue is made from a run with a linked inventory, that inventory is automatically linked to the issue

Issues can be linked multiple inventory items at the same time to allow you to process and disposition identical problems under one issue ticket.

<figure><img src="/files/7fA8d8alhRp2nbKulCxx" alt="" width="321"><figcaption><p>Parts Associated with the Issue AND Related POs</p></figcaption></figure>

{% hint style="info" %}
Issues can be also opened on [tool inventory](/features/tools).
{% endhint %}

### Issues On Runs

Issues can also be linked to runs in multiple ways.

* When an issue is made from a run or from failing a step, the run is automatically linked.
* Redlines can be linked to steps on runs to indicate work associated with the issue
* When making an issue manually, you can add a run and step where the problem was found.
* Issues have a [Must Close By](#blocking-progress-on-runs) field that, when set, blocks run progress based on the issue’s status.

<figure><img src="/files/ElnVjm5Zp8jQ6l14cgXa" alt="" width="321"><figcaption><p>Run Step Related to Issue</p></figcaption></figure>

<figure><img src="/files/iPscbb4S54VjuXXKKrHM" alt="" width="321"><figcaption><p>Related Issues - Including Parts AND POs</p></figcaption></figure>

#### Value

The redesigned cards allow for easier viewing of information related to the issue. In some cases they provide even more information than they used to while keeping the design minimal and allowing users to intuit what actions can be performed from the cards or dropdowns on the cards.

### Blocking Progress on Runs

The "Resolve Issue by Step" feature on the issue ticket allows the assignment of resolution to any step within the run. This could be:

* The same step where the issue was found, halting work until it’s resolved.
* The final step in the run, ensuring all issues are addressed before completion.
* Any step in between.

If the selected step is downstream of the step where the issue was found, that step cannot begin until the issue is resolved.

<figure><img src="/files/65CvXijIqSeyA78rWvqY" alt="" width="563"><figcaption><p>Blocking Run step set</p></figcaption></figure>

## Issue Indicators

Issues are indicated across ION by a warning sign (⚠️) and an orange badge.

Objects in ION with issues will display the issue badge and show a numeric count of issues attached to that object in a “M / N” format

* The first number indicates the number of unresolved issues on that object
* The second number indicates the total number of issues on that object.

You can click on the issue badge to see more information about the linked issues and navigate to them.

<figure><img src="/files/IxETSgAUSwJmXXYblHn2" alt="" width="375"><figcaption></figcaption></figure>

## Other Functionality:

* Containerization reduces eye fatigue and focuses users attention on long form issue descriptions.
* Performance improvements such as time to load first content.
* Outside Processing Steps (OSP) are brought to life with their POs being visible.
  * Irremovable label when the step the issue was found on is an OSP step
  * POs associated with parts are shown as a dropdown of that inventory
* Further Actions will be able to be created directly from the Issue Page. This close relation will allow you to continue solving problems while not holding up the resolution of individual issue occurences.

#### Value

With issue resolution being linked to the same run step in which the issue was found on, faster resolution of said issue can occur. This is the most stringent issue resolution timeframe ever made possible. Negate any risk by completely blocking progress. (Don't worry, we still have the flexibility to proceed on the run if you wish, just don't populate the field with the step the issue was found on!) Further Actions will be easily accessible to round out quality solutions and make including suppliers involved in OSP steps more visible within ION.

## Best Practices:

1. We'd recommend creating issues in the following manor for best traceability throughout your production line. This will empower your supply chain and manufacturing teams with the highest quality data to drive change at your organization.

<figure><img src="/files/wS3NApuoXn4l7P0mL1tF" alt="" width="375"><figcaption><p>Best Practice Issue Flow</p></figcaption></figure>

2. You can always understand the history of a part through its transaction history report in the inventory view. This is especially powerful when dealing with issues involving a component removed from an assembly and resolved separately. By following the best practice process outlined above, you can still see the original aBOM that the component was a part of through the transaction history view.

   <figure><img src="/files/OiqP7McPX8UyaC4KuXkt" alt=""><figcaption><p>Part Inventory Transaction History</p></figcaption></figure>


# Further Actions - CAPA

How You Can Handle CAPA Programs Within ION

## Overview

The issue ticket is the most direct connection to the manufacturing floor within ION Factory OS. This connection allows ION issue tickets to be automatically populated with details such as associated parts, processes, responsible teams, and supplier-related documentation. With all this information in one place, the responsible engineer can quickly determine the disposition and resolution of the issue.

The workflow continues in ION through a redlining process that captures the corrective actions needed to fix the occurrence. The final step involves relating those corrective actions to further actions. These further actions enable manufacturers to implement comprehensive changes to their processes or effectively communicate to resolve supplier-related issues, even after closing the original ION issue ticket. This is a necessary continuation of any quality process.

First Resonance has started the roll out of this feature. If you are interested in this capability please reach out to the team to get involved and benefit from giving early input.

## Content

Within Furthers Actions there are three main body text fields. Natively those fields are called "Problem Statement", "Analysis Notes", and "Resolution". We realize that there may be specific terminology that you want to use for your quality process and thus ***(COMING SOON)*** we allow organizations to customize what these fields say, just like we do for our standard "[Issue](/features/quality/issues)" ticket. That being said we want to express the intent of these fields as they are used throughout ION to capture insights into your process.

<table><thead><tr><th width="130">Section</th><th width="414">ION Definition</th><th>Common Alternatives</th></tr></thead><tbody><tr><td>Problem Statement</td><td>This field captures a clear, concise description of the issue being addressed. It should include specifics on what went wrong, the context in which it occurred, and any observed impacts on the product, process, or performance. The goal is to establish a shared understanding of the problem's nature and scope.</td><td>Failure Summary, Incident Report, Opportunity For Improvement</td></tr><tr><td>Analysis Notes</td><td>This section provides a detailed investigation of the root cause(s) of the problem. It may include contributing factors, relevant background information, and findings from diagnostic efforts or testing. The Analysis Notes aim to offer a thorough examination of why the issue occurred, supporting an informed approach to resolution.</td><td>Root Cause Analysis, Fishbone Breakdown, Observations and Findings</td></tr><tr><td>Resolution</td><td>The Resolution field outlines the steps taken to correct the problem and prevent recurrence. This may include corrective actions, preventive measures, and any process adjustments made. The resolution should be specific and actionable, detailing how each part of the solution addresses the identified causes of the problem. Utilize runs to capture these actions!</td><td>Mitigation Steps, Action Plan, Preventative Actions</td></tr></tbody></table>

## Use Cases

1. Supplier Related ION Issues and Supplier Corrective Actions

<figure><img src="/files/D1DWZ1A90V01agoA8KDc" alt=""><figcaption></figcaption></figure>

Use Case #1 in Action:

{% embed url="<https://www.loom.com/share/7d9b11d11ab24747a80ba945a0b719a3?sid=fd940fbc-e453-435e-90ac-eef83281f141>" %}

2. Groupings of ION Issues to Address Deep Seated Root Cause

<figure><img src="/files/ucH0ugKWTmVChkFoTk7C" alt=""><figcaption></figcaption></figure>

Use Case #2 in Action:

{% embed url="<https://www.loom.com/share/040574f236644535948331a4bdf5586d?sid=2160f1a0-20db-4b65-975b-b3db74f05e10>" %}

3. Further Actions to Capture Non-ION related Continuous Improvement Opportunities

<figure><img src="/files/LU1cAJkbBobWLBZMgHPh" alt=""><figcaption></figcaption></figure>

Use Case #3 in Action:

{% embed url="<https://www.loom.com/share/aa7a1117acbc4839bb2bb2434f3faff2?sid=1f88ed42-4ddc-4c09-9f5b-bdacf0a2adc8>" %}

4. Further actions are not just limited to the cases above. The overall flexibility these tickets offer lend themselves to good containers for a variety of objectives while still maintaining traceability back to core ION Objects. Link parts, runs, and issues however you like to create a network of connections with Further Actions.

## Best Practices

#### Effectiveness Reviews

To complete the loop on Further Actions, reviewing their effectiveness is often a key step in standard quality workflows. Within ION Further Actions, you can configure a "select" type attribute in your organizational settings to capture the outcome of these reviews.

<figure><img src="/files/kiWJhMevmnWOsGuPpAVg" alt="" width="375"><figcaption><p>Attribute Setup</p></figcaption></figure>

Populate this attribute with possible outcomes, and track them in aggregate using the Effectiveness Review tab in the ION Analytics Further Actions dashboard.

<figure><img src="/files/EyHggK2NVOYSKiZd7TMO" alt="" width="375"><figcaption><p>Dashboard Setup</p></figcaption></figure>

In the dashboard, enter the name of the attribute you created in the "Effectiveness Review Attribute Name" field to link it properly.

#### Creating Resolution Actions

Define your actions for the Further Action and track progress against them.

Create one plan with all your actions within it OR create each action in a unique plan to be as granular as you wish.

<figure><img src="/files/7TUIRaTkmlV662XaSAFT" alt="" width="375"><figcaption><p>Create and view actions to be taken</p></figcaption></figure>

Define the actions needed in two ways.

* Create a blank plan and free form add steps to accomplish the requirements for resolution.

  <figure><img src="/files/KiI6NWgAbuE4ifbtX98z" alt=""><figcaption><p>Define the steps needed for resolution.</p></figcaption></figure>
* Utilize a known process for resolution when repeat actions are needed. Choose a procedure that is templated to solve the specific occurrence.

  <figure><img src="/files/InTQi0K76gpegjGUnpdU" alt="" width="375"><figcaption><p>Setup your actions through standardized procedures</p></figcaption></figure>

#### When to Use the Canceled State for Further Actions

The **Canceled** state is useful for managing the relevance and priority of further actions within your organization. Here are the key points to consider:

1. **Accidental Creation**: If a further action is created by mistake, it can be moved to the **Canceled** state to indicate that the action is not needed.
2. **Editing Restrictions**: Further actions in the **Canceled** state cannot be edited. However, they can be moved back to the **In Progress** state if they were accidentally canceled.
3. **Avoid This Flow**: If a further action is approved and then needs to be canceled, it can be moved back to the **Approved** state as all approval requests have been satisfied. However, this practice is not recommended. See point four for the best practice.
4. **Ideal Workflow for Re-evaluation**: If a resolved further action is found to be insufficient, the recommended process is to **reopen** the further action. This will move the action back to the **In Progress** state, where necessary changes can be made, and the correct approvals can be requested. This approach avoids confusion and ensures that actions are appropriately tracked and managed.

By following these guidelines, you can maintain a clear and efficient workflow for managing further actions.


# Issues States, Dispositions, and Resolutions

Customize your issue disposition workflows according your organizational needs

## Issue Resolution Workflow

Issues can be moved through four states to track resolution. There are two decision points where sign off requirements can optionally be added to limit progress until the issue has been approved. Issues can also be moved backwards through the state workflow if necessary.

<figure><img src="/files/yNo8A2kpta7WY477YWEs" alt=""><figcaption><p>Ion Issues State Workflow with Redline Opportunities</p></figcaption></figure>

The following fields on an issue are editable in each state:

<table><thead><tr><th width="274">State</th><th>Editable Fields</th></tr></thead><tbody><tr><td><strong>Pending Status</strong></td><td><ul><li>Assignee</li><li>Cause Condition</li><li>Expected Condition</li><li>Disposition</li><li>Disposition Type</li><li>Issue Found On Run Step</li><li>Resolve Issue By Run Step</li><li>Inventory Issue Occurred On</li><li>Inventory Used to Fix Issue</li><li>Associated Redlines and their Content</li><li>Attachments</li><li>Custom Attributes</li><li>Label</li><li>Related Issues</li></ul></td></tr><tr><td><strong>Pending Status</strong> when atleast One Approval/Rejection has Been Made</td><td><ul><li>Inventory Issue Occurred On</li><li>Associated Redlines and their Content</li><li>Custom attributes</li><li>Labels</li><li>Related issues</li></ul></td></tr><tr><td><strong>In Progress Status</strong></td><td><ul><li>Assignee</li><li>Cause Condition</li><li>Expected Condition</li><li>Disposition</li><li>Disposition Type <em>(Moves issues back to Pending to go through approval process again)</em></li><li>Issue Found On Run Step</li><li>Resolve Issue By Run Step</li><li>Inventory Issue Occurred On</li><li>Inventory Used to Fix Issue</li><li>Associated Redlines and their Content <em>(Can only create new redlines on the issue found on run step)</em></li><li>Attachments</li><li>Custom Attributes</li><li>Label</li><li>Related Issues</li></ul></td></tr><tr><td><strong>In Review Status</strong></td><td><ul><li>Assignee</li><li>Custom Attributes</li><li>Attachments</li><li>Labels</li><li>Related Issues</li></ul></td></tr><tr><td><strong>In Review Status</strong> when atleast One Approval/Rejection has Been Made</td><td><ul><li>Labels</li><li>Related Issues</li></ul></td></tr><tr><td><strong>Resolved Status</strong></td><td><ul><li>Custom Attributes</li><li>Labels</li><li>Related Issues</li></ul></td></tr></tbody></table>

## Issue Dispositions

ION issues have a **Disposition** field, representing a method or category of resolving the issue. Depending on the severity and nature of the problem, different methods could be used requiring different levels of approval within the organization.

{% hint style="info" %}
The disposition field on an issue must be set before moving the issue through its workflow
{% endhint %}

ION Admins can configure the list of dispositions in the Organization Settings page. Each disposition has the following fields:

* **Active** controls if the issue disposition is selectable in an issue.
* **Name** controls what is shown in the disposition options
* **Description**
* **Approver Roles** lists the number and type of approver roles needed to move the issue from **Pending** to **In Progress**
* **Closure Roles** lists the number and type of approver roles needed to move the issue from **Review** to **Resolved**

<figure><img src="/files/Kdd3ghpSuAzodfL6snki" alt=""><figcaption><p>Add custom dispositions for issues in Settings</p></figcaption></figure>

## Approvals and Comments

Users may comment on the issue and approve/disapprove the issue content and disposition. Click the “Review” tab in the issue sidebar to see set approvers and a history of approvals and rejections for this issue.

To approve an issue, select a role and then select your name from the dropdown. Add your comment if desired and click **Approve** at the bottom of the dialog. The comment will appear in-line in the activity section below the issue disposition text field.

{% hint style="info" %}
With the team based notifications, a user and their team may be assigned to multiple approval requests. However, each user can only approve for one role on an issue.

Approving will approve required approvals and where the user is assigned first before approving on behalf of a team or additional approvals.
{% endhint %}

<figure><img src="/files/ATZCVXJSGzk3SqAnWgny" alt="" width="375"><figcaption></figcaption></figure>


# Quality Best Practices

## **Structured Approach to Inventory Scrapping with Integrated Traceability**

#### Objective

Establish a standardized and auditable process for scrapping inventory that ensures operational transparency, traceability, and regulatory compliance.

#### Strategic Rationale

* Enables data-backed decision-making when scrapping inventory
* Improves end-to-end traceability and accountability across the value chain
* Aligns with compliance mandates and audit-readiness standards

#### Recommended Workflow

1. **Inventory Identification**
   * You must first encounter a process in which scrapping is applicable.
   * For example:

     * Cycle count discrepancy
     * Non-conformance management

     <figure><img src="/files/eEMvOQVuteWDiivpIYlf" alt="" width="563"><figcaption></figcaption></figure>
2. **Issue Ticket Creation**

   * Avoid ad hoc scrapping; instead, log a structured issue
   * Define a clear rationale (e.g., "damaged components found on floor")
   * Incorporate relevant metadata (e.g., defect codes such as "electrical")

   <figure><img src="/files/ROLHDU1WSQMIlipjtfr4" alt="" width="375"><figcaption></figcaption></figure>
3. **Assign Disposition**

   * Apply your organizations standardized “Scrapped” disposition category.
     * An automation that allows for this functionality will need to be configured with this same disposition or list of dispositions that are intended to scrap inventory.
   * Specify downstream handling or review protocols (e.g., hazardous waste removal requirements) within the disposition notes

   <figure><img src="/files/BUd1ys0rqFFt1YPPIgrE" alt="" width="563"><figcaption></figcaption></figure>
4. **Issue Review and Resolution**

   * Route the issue through a review and approval gate
   * Upon approval, mark the issue as "Resolved"

   <figure><img src="/files/HTUqjG8GlidVf74cgBKR" alt="" width="563"><figcaption></figcaption></figure>
5. **Automated Inventory Adjustment**

   * Leverage automation to reflect scrapped quantity in inventory records
   * Maintain synchronized records of actions taken and materials impacted

   <figure><img src="/files/iXlFYBMTJik51dtXbsmi" alt=""><figcaption></figcaption></figure>

#### Automation Enablement

* Deploy the automation: **“Scrap Inventory on Scrapped Disposition”** via ION Marketplace in the navigation sidebar. Follow the prompts during setup to specify what dispositions result in scrap inventory.
* Ensures consistency, eliminates manual errors, and maintains a centralized audit trail

#### Deployment Recommendation

* Ensure clear articulation of scrapping rationale in every issue
* Maintain comprehensive attribute tagging for data segmentation and reporting
* Periodically review automation efficacy and process adherence

## **Best Practices for Documenting Redline Rationale**

#### Objective

Establish a robust methodology for capturing and surfacing rationale behind procedural redlines to ensure downstream clarity, traceability, and continuous improvement.

#### Strategic Rationale

* Ensures procedural edits are contextually informed and reviewable
* Supports closed-loop change management by tying redlines to root cause or issue feedback
* Increases visibility and accountability across procedure evolution

#### Recommended Workflow

1. **Option 1: Document Rationale Directly in the Redline**

   * Upon creating a redline, embed a clear and concise rationale within the redline itself
   * Enables future users and procedure owners to understand the intent behind the change

   <figure><img src="/files/nJpLTs1rMkdsh81MUepU" alt="" width="563"><figcaption></figcaption></figure>
2. **Link to Issues Where Applicable**

   * If the redline resolves a specific issue, associate it with the relevant issue ID or description
   * Ensures direct traceability between operational issues and procedural changes

   <figure><img src="/files/bMpheMeSUv5jZf2Fh19M" alt="" width="563"><figcaption></figcaption></figure>
3. **Review Redline History & Merge**

   * Once you have approved the redline, use the redline history interface to validate modifications
   * Click “Merge to Procedure” to transfer validated redlines into the procedural draft

   <figure><img src="/files/YYKQMFtzMybJSZhUAb55" alt="" width="375"><figcaption></figcaption></figure>
4. **Validate Integration into Procedure Draft**

   * Confirm that merged steps and associated rationale appear in the draft version of the procedure

   <figure><img src="/files/lleFXqYoYEQrWondHHTc" alt=""><figcaption></figcaption></figure>
5. **Option 2: Use Procedure Feedback Panel for Additional Context**

   * Navigate to the procedure feedback panel to leave contextual comments related to the redline or its impact
   * This feedback becomes visible at the procedure level and includes traceability to the specific step and run

   <figure><img src="/files/M1zYy9e47u0R8IK7Ldvc" alt="" width="375"><figcaption></figcaption></figure>

   <figure><img src="/files/9a1MrPTLkl8tNDvnqf59" alt="" width="375"><figcaption></figcaption></figure>
6. **Examples of Rationale to Capture**
   * Material availability
   * Process instability
   * Safety compliance
   * Training or documentation gaps

#### Deployment Recommendation

* Mandate rationale documentation for all redline changes
* Regularly review unresolved feedback and related issues prior to procedural release

## Associating Inventory To Issues

#### Overview

When logging issues in the workflow, it’s important to accurately link related parts to maintain clear traceability and context. This section outlines best practices and behaviors within the system when associating parts with an issue.

#### Logging Issues Against Parts

* **Primary Guideline:** Always log the issue against the part where the issue was first **found**.
* These parts appear under the section labeled **“Part the issue occurred on”,** this section should be used to attach any part inventories that are relevant to the issue.

#### Adding More Parts

* As the investigation progresses, additional parts may be linked to the same **"Part the issue occurred on"** field if further discoveries reveal contributing or root causes.
* **Best Practice:** Capture *all* parts relevant to the issue — there is no limit to the number of parts that can be added.
* This ensures comprehensive traceability, especially during disposition and root-cause analysis.

#### Parent/Child Relationships

The system provides enhanced visibility when related parts share a **parent/child relationship** through their aBOM (assembly Bill of Materials).

#### Interface Behavior

* When two parts linked in the “Issue was found on part” section are connected via their aBOM:
  * The interface visually distinguishes which part is the **parent** and which is the **child**.
  * This helps clarify actions such as:
    * Determining which part requires **disassembly** from another
    * Identifying which part should be **held** before proceeding with an integration run

#### Offending Part Label

* The **child part** in the parent/child relationship is automatically tagged with an **“OP - Offending Part”** label when both inventories are associated with the same issue.
* This is a **UI-only feature** and does **not** affect or tag inventory in any physical or database sense.

  * For example, if the child part is uninstalled from the parent, the relationship no longer applies and the label is removed.

  <figure><img src="/files/q80gIVGa7mMcp6pK0BY7" alt="Metal Slab is installed onto Metal Bracket and is this shown as an offending part"><figcaption><p>Metal Slab is installed onto Metal Bracket and is this shown as an Offending Part (OP)</p></figcaption></figure>

#### Installation Context

* Any part attached to the issue displays its installation context if it fulfills an aBOM requirement, providing additional situational awareness.

  <figure><img src="/files/l50r12fpPn4Ye1NJSXIN" alt=""><figcaption></figcaption></figure>

#### **Flow Diagram**

1. We'd recommend creating issues in the following manor for best traceability throughout your production line. This will empower your supply chain and manufacturing teams with the highest quality data to drive change at your organization.

<figure><img src="/files/wS3NApuoXn4l7P0mL1tF" alt="" width="375"><figcaption><p>Best Practice Issue Flow</p></figcaption></figure>

2. You can always understand the history of a part through its transaction history report in the inventory view. This is especially powerful when dealing with issues involving a component removed from an assembly and resolved separately. By following the best practice process outlined above, you can still see the original aBOM that the component was a part of through the transaction history view.

   <figure><img src="/files/OiqP7McPX8UyaC4KuXkt" alt=""><figcaption><p>Part Inventory Transaction History</p></figcaption></figure>

#### Future Improvements

We recognize that issue-to-part relationships provide valuable context when analyzing and resolving issues. To enhance this, our roadmap includes plans for expanding and formalizing these relationships across the platform and data products in 2026.

Planned relationship types include:

* **Found on** – where the issue was discovered
* **Caused by** – part identified as the root cause
* **Fixed by** – part or action that resolves the issue
* **Must contain** – dependencies or required relationships

These improvements aim to make relationships more meaningful, searchable, and insightful throughout the system.


# Tools

ION **Tools** can record assets and calibrated equipment in your factory. Tools are laid out in a very similar way to [**Parts**](/api/examples/parts-and-part-revisioning) with a few changes.

* Tools are always serialized - there are no lot-tracked tools
* Tool models can optionally have a **maintenance interval** and individual tools can have a **last maintained date**
* Tools can be assigned a **type** used to group tools beyond part number. For example, all torque wrenches of different model numbers can be combined under a single "Torque Wrench" type. This is useful if you want to call out use of a tool in a Run but don't need a specific part number.

![The Tool Library interface used to add tools](/files/KcpkFzC9HtQ1VwBGRnJg)

![Tool inventory showing tool serial number barcode, service status and location](/files/300DBAfmfDJhCbSIbE0B)

## Maintenance Interval

The maintenance interval is set in the part in tool library and applies to all tool inventory using that part. The interval is entered with as a list of format {**number**}{**unit**} using the following unit shorthand:

<table><thead><tr><th width="374">Shorthand</th><th width="374">Unit</th></tr></thead><tbody><tr><td>s</td><td>Second</td></tr><tr><td>m</td><td>Minute</td></tr><tr><td>h</td><td>Hour</td></tr><tr><td>d</td><td>Day</td></tr><tr><td>w</td><td>Week</td></tr><tr><td>month</td><td>Month</td></tr><tr><td>y</td><td>Year</td></tr></tbody></table>

For example, entering an interval of "1d20m" means an inverval of 1 day and 20 minutes, or 1480 minutes

## Tool Status

Tools have two statuses, **Available** and **Unavailable**.

The status of a tool can be determined by a couple of factors but also comes with a way to override the built in calculations:

1. If the tool has a maintenance interval and a last maintenance date, their maintenance status is calculated as **Available** depending if the next maintenance date is in the future. If the next maintenance date is in the past, the tool is **Unavailable**.
2. Tools located at an unavailable location they are marked unavailable.
3. Either of these calculations can be manually overridden by toggling the **Available / Unavailable** indicator within the tool inventory panel. This provides flexibility to adjust tool availability based on factors of your choosing, such as integration with a tool management system.

*Note: If you are interested in enabling this functionality please reach out to your Customer Success Manager.*

<figure><img src="/files/MStLfp9b3MjIGHOGDCUo" alt=""><figcaption></figcaption></figure>

## Tool Barcodes

Printing barcodes and using tool [barcodes](/features/barcode-labels) works just like Part Inventory. Tools also share [barcode templates](/features/barcode-labels/templating) with Inventory.

## Tracking tool usage

Tool usage can be tracked by using a **Tool Field** on a step in a run. When a technician is working on the run they will fill out the tool field and create an auditable log of the tool's usage.

When creating the data collection field, you can set the field name and help text as usual. Selecting the **Available** checkbox limits valid tool input to tools with the available status.

<figure><img src="/files/6ZSi8gIalDcSTjc9Bo6E" alt=""><figcaption><p>Adding a tool field to a step</p></figcaption></figure>

Use the **Validations** menu to constrain what kind of tools are valid input. Acceptable validations are **Type** for multiple models of tools or **Part Number** for a specific model.

<figure><img src="/files/jXL8hX88viFuyI4GocJV" alt=""><figcaption><p>Adjusting tool field validations</p></figcaption></figure>

When executing a run, select the tool you are using from the list to complete the field.

<figure><img src="/files/BVosME9lv0tClusjSVC9" alt=""><figcaption><p>Successful record of tool usage</p></figcaption></figure>

## Tools on Runs

Tools can be associated with [Runs](/features/runs) to inspect or maintain them. Associate a tool with a run just like you would a part during run creation.

<figure><img src="/files/S1AJ8n8mBdA8naaZikGP" alt=""><figcaption><p>Creating a run to maintain a tool</p></figcaption></figure>

## Tools on Issues

[Issues](/features/quality/issues) can be opened on tools just like part inventory. Tools will appear in the part inventory dropdown when creating or modifying an issue.

## Tools on Kits

Tools can be used in [Kits](/features/kitting) to move tools between different [Locations](/features/locations), or to request tools in a specific area or to a specific user. Requesting or moving a tool works the same as requesting or moving inventory.


# Locations

ION **Locations** record where work is done throughout the manufacturing environment. They can be used to record where parts are received, tools and inventory stored, and where work is done.

![Location hierarchical view](/files/m3lU6YA2rmNpg0GE3yrY)

Locations can be set up hierarchically. For example, a building can be given a location and contain locations for different rooms, each containing shelves, desks and parts.

Click on a location in the hierarchical view to see the detail view for that location including the supervisor of that location along with runs, inventory,

![Location detail view](/files/QrJnzcWuvW6CAXqmtVQl)

Locations can be deleted. In order to do so, the location can not be selected under the organization's purchase order setting for default ship to/bill to locations.

{% embed url="<https://www.loom.com/share/5bc72b1657b64cef97039ff9ae73c3ba>" %}


# Attributes

**Attributes** allow administrators of ION to add custom, non-native data fields to objects in ION. Along with [**Labels**](/features/labels) this can be used to link and extend items within ION to suit your workflow.

Each object type can support an unlimited number of attributes. Attributes can have the following data types:

* String (text)
* Number
* Boolean
* Single Select
* Multiple Select
* Timestamp
* File attachment
* ION User
* ION Part

Attributes can be defined for each object type in [**Settings**](/features/application-settings)

![Example Part Inventory attribute configuration menu in Settings](/files/QcK5veFecpvoVFeKFDSw)

![Attributes added to the Issues object in ION](/files/txqAYIW0KwhvMj3jKc9f)

### Updating Attribute or Attribute Options

Changing an attribute name or type or an attribute option requires you to make a new attribute or option and copy over the data from the previous attribute or option into the new one. Once the data has been successfully copied and verified, delete the previous attribute or the previous attribute option.

Deleting attributes is ***non-destructive*** meaning you can safely delete Custom Attributes while still retaining full traceability of those attributes in Ion. Attributes once "deleted" will disappear from the UI of their related objects (both new and historical). Attribute data however will still be accessible via ION Analytics and any accounts / queries / scripts tapping into the [ION data connector](/ion-analytics/data-connector).

### Copying Objects in ION

Whenever objects are copied in ION, all attributes are copied by default. See example use cases below:

* Splitting an Inventory Line
* Copying a Purchase Order
* Creating a new Part Revision. (Mutation: `createPartRevision`)

Examples where this does not occur:

* Creating a new part. (Mutation: `createPart`)


# Labels

**Labels** can be applied to many different object types in ION to organize them. The same label library is shared between all object types and can be used to group procedures, runs, purchases and issues together.

![Labels added to a procedure](/files/vvw1sHXQYgPrTXU6MKGR)


# Deleting labels

Delete labels using the API

### Overall

Deleting a label will remove it from all places with ION. See below for steps on how to delete it via the API (not available in the UI yet).

{% embed url="<https://www.loom.com/share/680ada89440e4771812f781c0153ad73?sid=a4850b80-4f1e-48f9-9f5b-481047d5ac94>" %}

### Steps

1. Query for the label

*Make sure to replace the values between the angled brackets.*

```graphql
{
  labels(filters: {value: {eq: <your label here>}}) {
    edges {
      node {
        id
        _etag
        value
      }
    }
  }
}

```

2. Delete the label

```graphql
mutation DeleteLabel($id: ID!, $etag: String!) {
  deleteLabel(id: $id, etag: $etag) {
    id
  }
}

```

with the below variables:

```graphql
{
  "id": <id from previous step>,
  "etag": <etag from previous step>
}
```


# Notifications

Notifications notify users and teams of status changes, approval requests, comments, mentions, and assignments across the platform via in-app notifications and emails!

{% hint style="info" %}
At the moment, team based notifications only apply to run step sign offs, issue assignments, and issue approvals. team notifications will be rolled out to the rest of the platform over time.
{% endhint %}

## Subscriptions

Users that are subscribed to objects (i.e. issues, procedures, etc.) will receive future notifications for that object that are detailed below. *Creating* an object or *assigning* a user to that object automatically subscribes that user to that object. In addition, users can be manually subscribed and unsubscribed as seen below.

<figure><img src="/files/2sb1yiXDBtIFSurRbYOa" alt=""><figcaption><p>Subscribe and Unsubscribe to Receive Notifications Related to that Object</p></figcaption></figure>

## Notification Types

### Platform Wide:

These are notifications that are triggered throughout the application.

* **Comment**: Indicates someone has commented on an object a user is subscribed to.
* **Mention**: The user is @ mentioned in a *comment*

### Issues:

Issue notifications are sent to any issue subscribers. If the issue is related to a run, then all subscribers of that run will automatically be subscribed to the issue.

* **Issue Created:** Indicates that an issue has been created.
* **Issue Status Change:** Indicates that an issue has changed status.

Certain issue notifications are only sent to the assignee and not to all issue subscribers. Those notifications are listed below.

* **Issue Assigned**: Indicates that a user has been assigned to an issue.
* **Issue** **Approval** **Request**: Indicates to a user that they have been requested to review an issue.

### Part Kits:

Part kit notifications are sent to any part kit subscribers.

* **Part Kit Status Changed**: Indicates that a part kit has changed statuses.

Certain part kit notifications are only sent to the assignee and not to all issue subscribers. Those notifications are listed below.

* **Part Kit Assigned**: Indicates that a user has been assigned to a part kit.

### Procedures:

Procedure notifications are sent out to any procedure subscribers and all requested procedure reviewers.

* **Procedure Status Changed**: Indicates that a procedure has changed status, except for when the status is changed to `released`.
* **Procedure Released**: Indicates that a procedure has been released.
* **Approval:** Indicates that someone has left an approval, denial, or a comment review.

Certain procedure notifications are only sent out the assignee and not to all procedure subscribers. Those notifications are listed below.

* **Approval Request:** Indicates that a user or their team has been assigned to review a procedure.

### Runs:

Run notifications are sent out to any users who subscribe to the run.

* **Comment:** Indicates that a user has created a comment.
* **Run Step Change:** Indicates that a step within a run has changed status.

Certain run notifications are only sent out the assignee and not to all run subscribers. Those notifications are listed below.

* **Run Assigned:** Indicates that a user has been assigned to a run.
* **Run Step Assigned:** Indicates that a user has been assigned to a run step.
* **Sign Off:** Indicates that a user has been requested to sign off a run step field.

### Purchases:

* **Purchase Assigned:** Indicates that a user has been assigned to a run.

### Standard Steps

* **Standard Step Approval Requested:** Indicates that a user has been assigned to review a standard step.

### Custom Notifications:

If you are interested in creating custom notifications on certain events you can configure them through the API here: [Notifications](/api/examples/notifications). Contact your system administrator or customer success representative if you need assistance.


# Search

Navigate throughout ION Quickly

{% embed url="<https://www.loom.com/share/d3e446afd08740f0a26ba29b5787743e?sid=8c197b00-bb68-4ea1-a4ab-251a078afbe0>" %}

ION Search is a way to navigate with ION. It can be opened from any screen within ION with the button combination **CTRL+K** on Windows/Linux or **⌘+K** on Mac. Alternatively, click on the magnifying glass in the sidebar.

![The opened Search bar](/files/5bCop8jLZ3MwcJQ6lUi5)

Navigate the search bar using the arrow keys and use **Enter** to select. You can use use close Search by clicking out of the popup, hitting the same key combination or by using the **Escape** key. You can also use search to find both main pages, help documents, or specific pages within ION. More on that below.

## Command List

After opening the search bar you will be presented with a list of commands. Click **See More** in the top right hand corner to see the full list of commands. Navigate to any command using the mouse or keyboard.

{% hint style="info" %}
The key combinations shown on each command are keyboard shortcuts. They can be executed without having to open the search bar.
{% endhint %}

## Search

ION Search also supports keyword search of ION objects like Runs, Procedures, Issues, Locations, Purchases, and Parts. The search function is triggered automatically after typing.

![Command bar searching within ION](/files/JMMjpmaHj4ZzaKLyiwhz)

## Help Docs

Scroll through the **Help** section of the command bar to see all the manual entries at [manual.firstresonance.io](https://manual.firstresonance.io).

{% hint style="info" %}
You can also directly search the ION manual by typing your query into the command bar.
{% endhint %}


# ION Assistant

Compose GraphQL queries, retrieve data and get your questions about ION answered more quickly.

{% hint style="warning" %}
The Assistant is currently in beta testing with a few select customers. It is not currently available to any Gov Cloud customers.
{% endhint %}

## What is ION Assistant?

The ION Assistant is a cutting-edge [Generative AI](https://en.wikipedia.org/wiki/Generative_artificial_intelligence) solution designed to assist ION users with a variety of tasks, including composing GraphQL queries and mutations, answering questions about ION, retrieving data, and handling other essential functions.

## Types of questions

{% tabs %}
{% tab title="General questions about ION" %}

<figure><img src="/files/XvmyqtPjymuN7ZbCVrMX" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Query recommendations" %}

<figure><img src="/files/inxutMwp8ZLCWuUAODi3" alt=""><figcaption></figcaption></figure>
{% endtab %}

{% tab title="Mutation recommendations" %}

<figure><img src="/files/rl2FSodA7foEOirPN9Hi" alt=""><figcaption></figcaption></figure>
{% endtab %}
{% endtabs %}

## Getting started with the Assistant

To begin using the tool, locate the Assistant icon on the main page in the lower left corner.

<figure><img src="/files/HdtWzRvSqzXZfzJfOWfV" alt=""><figcaption><p>If you don't see the icon, please reach out to the First Resonance team.</p></figcaption></figure>

After clicking the button, you'll be redirected to a page where you can ask your questions to the Assistant. But before exploring what the Assistant can do for you, let's first familiarize ourselves with the user interface.

<figure><img src="/files/Fp9F2uCDPLUSdDWxANFR" alt=""><figcaption><p>User interface of the Assistant. Please continue reading the manual to understand each component marked with a letter code.</p></figcaption></figure>

To ask the Assistant a question, type it into the input box and press the 'Query' button **(A)**. The assistant will take a moment to understand your question, compile all the necessary information, and provide an answer within 5 to 15 seconds. Depending on the type of answer, you will either see a GraphQL query or a formatted response **(B)**. You can either copy the content of the response **(C)**, or if it's a GraphQL query, you can run or edit it **(D)**. If you appreciate the response, feel free to press the 'Thumbs Up' button. Conversely, if you believe the Assistant's response could be improved, let us know by clicking the 'Thumbs Down' button. We'd love to see your feedback! If you have some additional comments please use 'Submit feedback' option.

With the quick UI tour completed, let's dive into Assistant's capabilities!

## What questions does the ION Assistant understand?

The ION Assistant is a general conversational chatbot. It can comprehend the same types of questions as ChatGPT, but it also possesses capabilities that other chatbots lack.

**The assistant knows who you are.** Each time you initiate a conversation, the assistant captures attributes of your ION account, such as your user ID. For example, try this question:

```
Tell me what issues are assigned to me
```

The chatbot will respond based on whether you have any assigned issues. If there are, it will return a list of these issues. If not, it will provide a GraphQL query that you can execute to fetch issues assigned to your ION ID.

**The assistant is well-versed in GraphQL and can help you learn it too!** We've made the Assistant not only an expert in crafting queries and mutations but also trained it to understand the ION API. When requesting a query or mutation response, remember to explicitly state it in your question. For example:

<pre><code><strong>What GraphQL mutation can I use to create a plan with name "Test"?
</strong>
<strong>Can you give me a query to fetch my user ID?
</strong></code></pre>

With a query at hands, you can ask assistant to explain it:

```
I do not understand this code, can you explain it to me?
```

Or you can ask assistant for advice on crafting your own queries.

```
What schema did you use to write this query?
```

**We've connected the assistant to your data.** Not only does the assistant know which query to use to retrieve data, but it can also take it a step further by executing the query, retrieving the data on your behalf, and using it to answer your question. Please note that the assistant uses your credentials to access the data. Therefore, it cannot retrieve data to which you do not have access. Try:

```
Can you calculate total number of issues assigned to me?
```

**It can answer your questions about ION.** The assistant is well-versed in ION features and can use this manual to answer your questions. Give this question a try:

```
What scripting language should I use for the Code attribute in ION Actions?
```

**Wait, there is more!** Out goal is to make assistant helpful to you. Remember that you have access to a chatbot that can answer your questions, convert the data into many different formats and more. For example, after you ran a GraphQL query that retrieves top 10 issues, try this question:

```
Can you convert this data into a Python list
```

Or try something more exotic:

```
Can you write me a short story about me?
```

## FAQ

**I've asked my question, but the assistant doesn't seem to understand me. Why?**

The assistant is trained to recognize the intent behind your question and will activate the appropriate part of the system to respond. Occasionally, it may not interpret your intent correctly. If this happens, try rewording your question. Sometimes asking follow-up questions helps to clarify your intent to chatbots.

**Can assistant take actions on my behalf?**

At this moment assistant only runs GraphQL queries that do not modify your data. If you'd like to make a change, you can ask assistant to give you a GraphQL mutation and run it.

**Is ION Assistant available for Gov Cloud customers?**

No, at the moment, we have only launched the assistant for Pub Cloud customers. We are in the process of enabling this feature for all clouds.


# Settings

Manage your organization and user settings in ion

## User settings

Click the settings cog in the main sidebar of ION. Clicking into the User submenu, you can modify your user settings. This includes your avatar and your name. Setting these will help your team identify you throughout ION.

## Organization settings

Organization admins can modify the organization's settings, including the organization's avatar and name. It also lets you set up custom attributes, the issue review process, and more.

* **General Settings:** Here, you can update your company name and your ICON. You'll have to link to an internet image for now, as ION does not support a direct image upload. You'll also see the number of members your environment has, and you can update your sidebar color as well.
* **DateTime:** Here, you can update the way that dates are reflected in ION
* **Allowed Domains:** Here, you can update who and which domains can access your ION environment. There is also a switch to flip on our end (a double check for extra security), which allows us both to control who is in each environment.

{% hint style="info" %}
If you want to add another domain to your environment, please reach out via email to <support@firstresonance.io>.
{% endhint %}

All the other organizational settings allow you to add custom attributes for the different entities in ION.

### Members and roles

As an organization admin, you can set the roles for the members of your company using IO&#x4E;*.* Admins can add "engineer" or "technician" roles to users. By default, the "engineer" role allows users to create and modify procedures, while the "technician" role allows the user to execute and complete runs. If you want a user to be able to do both, you can set both "engineer" and "technician" roles, and you can also add your own roles as desired. Admins can also give other users admin permissions. See more in the [role based access control ](/features/application-settings/role-based-access-control)section.


# Role based access control

### Overview

Role based access control allows for assigning users custom permissions within ION for creating/updating/deleting data. The ION data model allows for abstracting permissions to roles to make them easier to administrate.

Permissions are assigned to roles, and roles can either be assigned directly to users or to users through teams. *See the data model below.*

![Hight level data model](/files/FP8nPh9iYWF7rXzG0BSx)

Let's take an example. Let's say that you want to control the permissions of creating runs to the manufacturing engineering team. You'd also like manufacturing engineers to have access to create and update inventory. The warehouse team will have access to create and update inventory as well.

A recommended approach for doing this in ION would be:

1. Create a new role for `Run creator`
2. Assign the appropriate permissions to role
3. Create the teams: `Manufacturing engineering` and `Warehouse.`
4. Assign the correct roles to the teams, which in this case will include `Run Creator` and the `inventory` role, which already exists in ION.

![](/files/twM7XZ3Ak8K2wogNaINE)

5\. Assign the correct staff to each team

6\. Go forth and prosper with your newly administered roles

## Creating and Assigning Roles to Users

To grant users access to new roles, you either need to be an `admin` or you need to have a role with the `AttachRoleToUser` or `DetachRoleFromUser` permissions.

To change the permissions associated with a role or to create new ones, you need the following permissions.

* AttachPermissionGroupToRole
* CreateRole
* DeleteRole
* DetachPermissionGroupFromRole
* UpdateRole

{% hint style="info" %}
As a rule of thumb, every unique mutation in ION has an associated permission with it. See [Interactive API explorer](/api/interactive-api-explorer) for more details.
{% endhint %}

### Admins

Users with the role `admin` will have permissions to do any and all things within ION. Use judiciously!

To see others that are admins within your environments, navigate to roles within the members section of settings here and see who all this applies to.

<figure><img src="/files/MQPJEqwD8oAGbKODRIKH" alt=""><figcaption></figcaption></figure>

### ION Role

The `ION` role is a system-protected role automatically assigned to every user. It cannot be removed or unassigned. This role does not grant any permissions and exists solely to support system migrations, upgrades, and maintenance processes within the platform.

### Adding permissions to roles:

To add permissions to roles:

1. go to Settings -> Roles
2. Click on the role you want to edit
3. Click the permissions you want to add.

Below is a video showing just that!

{% embed url="<https://www.loom.com/share/714ff91a94d44e8881b0d5fb7ca2eb4e>" %}

### No permissions

If a user does not have permissions to perform an action, they will get the a message listing the permission required, see example below. Permissions are required for any create/update/delete action in ION.

![](/files/0XYCk5ZhnWTsGQvspN8c)

### Special cases

* Redlining on the frontend requires that you have access to the `updateRedline`Permission
* Putting a step on hold or canceling a step requires the same access as completing a step: `updateRunStep`

### Bulk updates

We've prepared some [bulk update python scripts](https://github.com/FirstResonance/ion-examples) here for managing users, roles, and teams to help make it easier to administer.


# Full Glossary of ION Permissions

Every permission in ION, along with a description of what they do.

* **addHeaderToWebhookReceiver**: Permits the user to add headers to a webhook receiver configuration.
* **addInputToPlan**: Permits the user to add inputs to a plan.
* **addInventoryToPurchaseOrderLine**: Permits the user to add inventory to a purchase order line.
* **addItemsToReceipt**: Permits the user to add items to a receipt from the purchase order, or by adding without PO.
* **addLabelToItem**: Permits the user to add labels to an item (run, procedure, kit, etc).
* **addLabelToProcedureFamily**: Permits the user to add labels to a procedure family.
* **addPartInventoryToRunStep**: Permits the user to add part inventory to a run step.
* **addPartsToKitFromMbom**: Permits the user to add parts to a kit from a manufacturing bill of materials (MBOM), i.e. using the button on the kits screen.
* **addPlanItemToPlan**: Permits the user to add plan items to a plan in the results table, i.e. if not already added via the plan inputs.
* **addRequirementToItem**: Permits the user to add requirements to an item; i.e. adding terms to a PO.
* **addResultToPlanItem**: Permits the user to add results to a plan item.
* **addSubtypeToPart**: Permits the user to add subtypes to a part (i.e. Tool)
* **addUserToTeam**: Permits the user to add users to a team.
* **archiveRun**: Permits the user to archive a run.
* **attachPermissionGroupToRole**: Permits the user to attach permission groups to a role (perform RBAC actions).
* **attachRoleToTeam**: Permits the user to attach roles to a team.
* **attachRoleToUser**: Permits the user to attach roles to a user.
* **cancelRun**: Permits the user to cancel a run.
* **cancelRunStepRedline**: Permits the user to cancel a redline.
* **checkIn**: Permits the user to check in to a run.
* **checkOut**: Permits the user to check out of a run.
* **cloneProcedure**: Permits the user to clone a procedure.
* **convertResultsFromPlanItem**: Permits the user to convert results from a plan item.
* **convertResultsFromPlanItems**: Permits the user to convert results from multiple plan items.
* **copyField**: Permits the user to copy a field in a step.
* **copyStandardStep**: Permits the user to copy a standard step.
* **copyStep**: Permits the user to copy a step.
* **copyStepToRun**: Permits the user to copy a step to a run.
* **createAbomForPartInventory**: Permits the user to create an assembled bill of materials (ABOM) for part inventory.
* **createAbomInstallation**: Permits the user to create an ABOM installation.
* **createApiKey**: Permits the user to create an API key.
* **createAsset**: Permits the user to add an asset on a run or procedure (i.e. file attachment).
* **createBarcodeLabel**: Permits the user to create a barcode label from Inventory, Kits, or Locations.
* **createBarcodePattern**: Permits the user to create a new barcode pattern in the organization settings.
* **createBarcodePrintRequest**: Permits the user to generate a print request specific to barcodes.
* **createBarcodeTemplate**: Permits the user to create a barcode template in the organization settings.
* **createBuildRequirement**: Permits the user to create a build requirement for an aBOM.
* **createBuildRequirementReferenceDesignator**: Permits the user to create a build requirement reference designator for an aBOM.
* **createBuildRequirementSubstitute**: Permits the user to create a build requirement substitute for an aBOM.
* **createComment**: Permits the user to write comments in ION.
* **createContact**: Permits the user to create a contact.
* **createCurrency**: Permits the user to create a currency (API only for now).
* **createDatagridColumn**: Permits the user to create a datagrid column in a datagrid step.
* **createDatagridRow**: Permits the user to create a datagrid row in a datagrid step.
* **createFileAttachment**: Permits the user to upload a file attachment.
* **createIntegration**: Permits the user to create a new integration.
* **createInvite**: Permits the user to invite another person to ION.
* **createIssue**: Permits the user to create an issue ticket.
* **createIssueApproval**: Permits the user to approve an Issue.
* **createIssueApprovalRequest**: Permits the user to ask someone to approve an Issue.
* **createIssueDispositionType**: Permits the user to create an issue disposition type in the organization settings.
* **createIssueDispositionTypeRole**: Permits the user to select the type of role that can approve a certain disposition on an issue.
* **createIssuePartInventory**: Permits the user to link part inventory to an issue.
* **createIssueRelation**: Permits the user to add related issues.
* **createIssues**: Permits the user to bulk create issues.
* **createKitForRun**: Permits the user to create a kit from a run.
* **createLabel**: Permits the user to create a label to tag a kit, procedure, run, etc.
* **createLocation**: Permits the user to create a new location.
* **createLocationSubtype**: Permits the user to create a location subtype.
* **createMbom**: Permits the user to create a manufacturing bill of materials (MBOM).
* **createMbomApproval**: Permits the user to approve an mBOM.
* **createMbomApprovalRequest**: Permits the user to request the approval of an mBOM.
* **createMbomApprovalRole**: Permits the user to add roles to approve to mBOM.
* **createMbomItem**: Permits the user to add parts to an Mbom.
* **createMbomItemReferenceDesignator**: Permits the user to add reference designators to mBOM items.
* **createMbomSubstitute**: Permits the user to add substitutes to mBOM items.
* **createMbomSubstitutes**: Permits the user to add more than one substitute to an mBOM item.
* **createMrpJob**: Permits the user to create a material requirements planning (MRP) job in Autoplan.
* **createMultipleMbomItems**: Permits the user to import an mBOM.
* **createOrganizationGlobalUniqueSerialNumberScheme**: Permits the user to create a serial number scheme for the organization.
* **createOrganizationPartRevisionScheme**: Permits the user to create a part revision scheme for the organization.
* **createPart**: Permits the user to create a new Part Library item.
* **createPartInventories**: Permits the user to bulk create part inventories.
* **createPartInventory**: Permits the user to create a part inventory.
* **createPartKit**: Permits the user to create a part kit.
* **createPartKitItem**: Permits the user to add parts to a kit.
* **createPartProcedure**: Permits the user to create a part-procedure relationship.
* **createPartRevision**: Permits the user to create a part revision.
* **createPartSubtype**: Permits the user to create a part subtype. Used for Tools.
* **createPartSupplier**: Permits the user to create a part supplier.
* **createPlan**: Permits the user to create a plan.
* **createPlanItem**: Permits the user to create a plan item.
* **createPlanItemAllocation**: Permits the user to create a plan item allocation.
* **createPlanReservation**: Permits the user to create a plan reservation.
* **createProcedure**: Permits the user to create a procedure.
* **createProcedureVersion**: Permits the user to create a version of a procedure.
* **createPurchaseOrder**: Permits the user to create a purchase order.
* **createPurchaseOrderApproval**: Permits the user to approve a purchaser order.
* **createPurchaseOrderApprovalRequest**: Permits the user to ask another user to approve a purchase order.
* **createPurchaseOrderFee**: Permits the user to add a purchase order fee to their PO.
* **createPurchaseOrderLine**: Permits the user to create a purchase order line.
* **createReceipt**: Permits the user to create a receipt.
* **createRedlineApproval**: Permits the user to approve a redline on a run.
* **createRedlineApprovalRequest**: Permits the user to ask another user to approve redlines.
* **createRequirement**: Permits the user to create a requirement for purchasing.
* **createReview**: Permits the user to create a review (via mBOMs, Issues, Procedures, etc).
* **createReviewRequest**: Permits the user to create a review request.
* **createRole**: Permits the user to create a new role.
* **createRule**: Permits the user to create a new rule.
* **createRun**: Permits the user to create a new run.
* **createRunBatch**: Permits the user to create a run batch.
* **createRunStep**: Permits the user to create a run step.
* **createRunStepEdge**: Permits the user to create a run step dependency.
* **createRunStepField**: Permits the user to create a run step field.
* **createRunStepFieldValidation**: Permits the user to add a run step field validation.
* **createRuns**: Permits the user to bulk create runs.
* **createStandardStepVersion**: Permits the user to create a new version of a standard step.
* **createStep**: Permits the user to create a new step in a procedure.
* **createStepApproval**: Permits the user to create a step approval.
* **createStepApprovalRequest**: Permits the user to create a step approval request.
* **createStepEdge**: Permits the user to create a step dependency.
* **createStepField**: Permits the user to create a step field.
* **createStepFieldValidation**: Permits the user to create a step field validation.
* **createStepMbomItemAssociation**: Permits the user to create an association between a step and an MBOM item.
* **createSupplier**: Permits the user to create a new supplier in the purchasing module.
* **createTeam**: Permits the user to create a new team.
* **createUnitOfMeasurement**: Permits the user to create a new unit of measurement.
* **createUserSubscription**: Permits the user to subscribe themselves or a user to something in ION.
* **createWebhookHeader**: Permits the user to create a webhook header.
* **createWebhookReceiver**: Permits the user to create a webhook receiver.
* **createWebhookSubscription**: Permits the user to create a webhook subscription.
* **deleteAbomInstallation**: Permits the user to delete an ABOM installation.
* **deleteApiKey**: Permits the user to delete an API key.
* **deleteAsset**: Permits the user to delete an asset such as a file attachment.
* **deleteBarcodePattern**: Permits the user to delete a barcode pattern.
* **deleteBuildRequirement**: Permits the user to delete a build requirement.
* **deleteBuildRequirementReferenceDesignator**: Permits the user to delete a build requirement reference designator.
* **deleteBuildRequirementSubstitute**: Permits the user to delete a build requirement substitute.
* **deleteComment**: Permits the user to delete a comment.
* **deleteContact**: Permits the user to delete a contact.
* **deleteCurrency**: Permits the user to delete a currency.
* **deleteDatagridColumn**: Permits the user to delete a datagrid column.
* **deleteDatagridRow**: Permits the user to delete a datagrid row.
* **deleteFileAttachment**: Permits the user to delete a file attachment.
* **deleteIntegration**: Permits the user to delete an integration.
* **deleteIssueApprovalRequest**: Permits the user to delete an issue approval request.
* **deleteIssueDispositionType**: Permits the user to delete an issue disposition type.
* **deleteIssueDispositionTypeRole**: Permits the user to delete an issue disposition type role.
* **deleteIssuePartInventory**: Permits the user to delete an issue part inventory.
* **deleteIssueRelation**: Permits the user to delete an issue relation.
* **deleteLabel**: Permits the user to delete a label.
* **deleteLocation**: Permits the user to delete a location.
* **deleteLocationSubtype**: Permits the user to delete a location subtype.
* **deleteMbom**: Permits the user to delete an MBOM.
* **deleteMbomApprovalRequest**: Permits the user to delete an MBOM approval request.
* **deleteMbomApprovalRole**: Permits the user to delete an MBOM approval role.
* **deleteMbomItem**: Permits the user to delete an MBOM item.
* **deleteMbomItemReferenceDesignator**: Permits the user to delete an MBOM item reference designator.
* **deleteMbomSubstitute**: Permits the user to delete an MBOM substitute.
* **deleteOrganizationGlobalUniqueSerialNumberScheme**: Permits the user to delete a global unique serial number scheme for the organization.
* **deleteOrganizationIssueAttributes**: Permits the user to delete issue attributes for the organization.
* **deleteOrganizationLocationAttributes**: Permits the user to delete location attributes for the organization.
* **deleteOrganizationMbomAttributes**: Permits the user to delete MBOM attributes for the organization.
* **deleteOrganizationPartAttributes**: Permits the user to delete part attributes for the organization.
* **deleteOrganizationPartInventoryAttributes**: Permits the user to delete part inventory attributes for the organization.
* **deleteOrganizationPartKitAttributes**: Permits the user to delete part kit attributes for the organization.
* **deleteOrganizationPartKitItemAttributes**: Permits the user to delete part kit item attributes for the organization.
* **deleteOrganizationPartRevisionScheme**: Permits the user to delete a part revision scheme for the organization.
* **deleteOrganizationPlanAttributes**: Permits the user to delete plan attributes for the organization.
* **deleteOrganizationProcedureAttributes**: Permits the user to delete procedure attributes for the organization.
* **deleteOrganizationPurchaseOrderAttributes**: Permits the user to delete purchase order attributes for the organization.
* **deleteOrganizationPurchaseOrderLineAttributes**: Permits the user to delete purchase order line attributes for the organization.
* **deleteOrganizationReceiptAttributes**: Permits the user to delete receipt attributes for the organization.
* **deleteOrganizationRunAttributes**: Permits the user to delete run attributes for the organization.
* **deleteOrganizationRunStepAttributes**: Permits the user to delete run step attributes for the organization.
* **deleteOrganizationStepAttributes**: Permits the user to delete step attributes for the organization.
* **deleteOrganizationSupplierAttributes**: Permits the user to delete supplier attributes for the organization.
* **deletePart**: Permits the user to delete a part.
* **deletePartInventory**: Permits the user to delete part inventory.
* **deletePartInventoryBuildRequirement**: Permits the user to delete a build requirement from part inventory.
* **deletePartKit**: Permits the user to delete a part kit.
* **deletePartKitItem**: Permits the user to delete a part kit item.
* **deletePartProcedure**: Permits the user to delete a part procedure.
* **deletePartSubtype**: Permits the user to delete a part subtype.
* **deletePartSupplier**: Permits the user to delete a part supplier.
* **deletePlan**: Permits the user to delete a plan.
* **deletePlanItem**: Permits the user to delete a plan item.
* **deletePlanItemAllocation**: Permits the user to delete a plan item allocation.
* **deletePlanReservation**: Permits the user to delete a plan reservation.
* **deleteProcedure**: Permits the user to delete a procedure.
* **deletePurchaseOrder**: Permits the user to delete a purchase order.
* **deletePurchaseOrderApprovalRequest**: Permits the user to delete a purchase order approval request.
* **deletePurchaseOrderFee**: Permits the user to delete a purchase order fee.
* **deletePurchaseOrderLine**: Permits the user to delete a purchase order line.
* **deleteReceipt**: Permits the user to delete a receipt.
* **deleteRedlineApprovalRequest**: Permits the user to delete a redline approval request.
* **deleteRequirement**: Permits the user to delete a requirement.
* **deleteReviewRequest**: Permits the user to delete a review request.
* **deleteRole**: Permits the user to delete a role.
* **deleteRule**: Permits the user to delete a rule.
* **deleteRunStep**: Permits the user to delete a run step.
* **deleteRunStepEdge**: Permits the user to delete a run step edge.
* **deleteRunStepField**: Permits the user to delete a run step field.
* **deleteRunStepFieldValidation**: Permits the user to delete a run step field validation.
* **deleteStep**: Permits the user to delete a step.
* **deleteStepApprovalRequest**: Permits the user to delete a step approval request.
* **deleteStepEdge**: Permits the user to delete a step edge.
* **deleteStepField**: Permits the user to delete a step field.
* **deleteStepFieldValidation**: Permits the user to delete a step field validation.
* **deleteStepMbomItemAssociation**: Permits the user to delete an association between a step and an MBOM item.
* **deleteSupplier**: Permits the user to delete a supplier.
* **deleteTeam**: Permits the user to delete a team.
* **deleteUnitOfMeasurement**: Permits the user to delete a unit of measurement.
* **deleteUserSubscription**: Permits the user to delete a user subscription.
* **deleteWebhookHeader**: Permits the user to delete a webhook header.
* **deleteWebhookReceiver**: Permits the user to delete a webhook receiver.
* **deleteWebhookSubscription**: Permits the user to delete a webhook subscription.
* **detachPermissionGroupFromRole**: Permits the user to detach a permission group from a role.
* **detachRoleFromTeam**: Permits the user to detach a role from a team.
* **detachRoleFromUser**: Permits the user to detach a role from a user.
* **dispatchNotification**: Permits the user to dispatch notifications.
* **generateReadEmbeddedAnalytics**: Permits the user to generate read operations for embedded analytics.
* **generateRunSummary**: Permits the user to generate a summary of a run.
* **generateWriteEmbeddedAnalytics**: Permits the user to generate write operations for embedded analytics.
* **importStepsFromPdf**: Permits the user to import steps from a PDF document.
* **installKitOnAbom**: Permits the user to install a kit on an assembled bill of materials (ABOM).
* **issueItemToKit**: Permits the user to issue an item to a kit.
* **mergePartInventory**: Permits the user to merge part inventory.
* **mergeRunStep**: Permits the user to merge a run step.
* **mergeRunStepToProcedure**: Permits the user to merge a run step into a procedure.
* **mergeRunStepToRuns**: Permits the user to merge a run step into runs.
* **moveItemToInventory**: Permits the user to move an item to inventory.
* **moveKitInventoryToLocation**: Permits the user to move kit inventory to a location.
* **removeHeaderFromWebhookReceiver**: Permits the user to remove a header from a webhook receiver.
* **removeInputFromPlan**: Permits the user to remove an input from a plan.
* **removeInventoryFromPurchaseOrderLine**: Permits the user to remove inventory from a purchase order line.
* **removeInventoryFromReceipt**: Permits the user to remove inventory from a receipt.
* **removeItemFromReceipt**: Permits the user to remove an item from a receipt.
* **removeLabelFromItem**: Permits the user to remove a label from an item.
* **removeLabelFromProcedureFamily**: Permits the user to remove a label from a procedure family.
* **removePartInventoryFromRunStep**: Permits the user to remove part inventory from a run step.
* **removePlanItemFromPlan**: Permits the user to remove a plan item from a plan.
* **removeRequirementFromItem**: Permits the user to remove a requirement from an item.
* **removeResultFromPlanItem**: Permits the user to remove a result from a plan item.
* **removeSubtypeFromPart**: Permits the user to remove a subtype from a part.
* **removeUserFromTeam**: Permits the user to remove a user from a team.
* **reorderDatagridColumn**: Permits the user to reorder datagrid columns.
* **reorderDatagridRow**: Permits the user to reorder datagrid rows.
* **reorderPurchaseOrderLine**: Permits the user to reorder purchase order lines.
* **reorderRunStepFields**: Permits the user to reorder run step fields.
* **reorderRunSteps**: Permits the user to reorder run steps.
* **reorderStepFields**: Permits the user to reorder step fields.
* **reorderSteps**: Permits the user to reorder steps.
* **resendInvite**: Permits the user to resend an invitation to someone in ION.
* **resetIssueApprovals**: Permits the user to reset issue approvals.
* **revokeInvite**: Permits the user to revoke an invitation to ION.
* **runStepDatagridOperations**: Permits the user to perform datagrid operations on a run step.
* **setDatagridValue**: Permits the user to set the value of a datagrid cell.
* **splitManyPartInventory**: Permits the user to split multiple part inventories.
* **splitPartInventory**: Permits the user to split part inventory.
* **splitUnfulfilledPartKit**: Permits the user to split an unfulfilled part kit.
* **stepDatagridOperations**: Permits the user to perform datagrid operations on a step.
* **updateAbomInstallation**: Permits the user to update an ABOM installation.
* **updateApiKey**: Permits the user to update an API key.
* **updateBarcodeLabel**: Permits the user to update a barcode label.
* **updateBarcodePattern**: Permits the user to update a barcode pattern.
* **updateBarcodeTemplate**: Permits the user to update a barcode template.
* **updateBuildRequirement**: Permits the user to update a build requirement.
* **updateBuildRequirementReferenceDesignator**: Permits the user to update a build requirement reference designator.
* **updateBuildRequirementSubstitute**: Permits the user to update a build requirement substitute.
* **updateComment**: Permits the user to update a comment.
* **updateContact**: Permits the user to update a contact.
* **updateCurrency**: Permits the user to update a currency.
* **updateDatagridColumn**: Permits the user to update a datagrid column.
* **updateDatagridRow**: Permits the user to update a datagrid row.
* **updateInputToPlan**: Permits the user to update an input to a plan.
* **updateIntegration**: Permits the user to update an integration.
* **updateIssue**: Permits the user to update an issue.
* **updateIssueApproval**: Permits the user to update an issue approval.
* **updateIssueApprovalRequest**: Permits the user to update an issue approval request.
* **updateIssueAttribute**: Permits the user to update an issue attribute.
* **updateIssueDispositionType**: Permits the user to update an issue disposition type.
* **updateIssueDispositionTypeRole**: Permits the user to update an issue disposition type role.
* **updateLabel**: Permits the user to update a label.
* **updateLocation**: Permits the user to update a location.
* **updateLocationAttribute**: Permits the user to update a location attribute.
* **updateLocationSubtype**: Permits the user to update a location subtype.
* **updateMbom**: Permits the user to update an MBOM.
* **updateMbomApproval**: Permits the user to update an MBOM approval.
* **updateMbomApprovalRequest**: Permits the user to update an MBOM approval request.
* **updateMbomApprovalRole**: Permits the user to update an MBOM approval role.
* **updateMbomAttribute**: Permits the user to update an MBOM attribute.
* **updateMbomItem**: Permits the user to update an MBOM item.
* **updateMbomItemReferenceDesignator**: Permits the user to update an MBOM item reference designator.
* **updateMrpJob**: Permits the user to update a material requirements planning (MRP) job.
* **updateOrganization**: Permits the user to update organization details.
* **updateOrganizationGlobalUniqueSerialNumberScheme**: Permits the user to update a global unique serial number scheme for the organization.
* **updateOrganizationIssueAttributes**: Permits the user to update issue attributes for the organization.
* **updateOrganizationLocationAttributes**: Permits the user to update location attributes for the organization.
* **updateOrganizationMbomAttributes**: Permits the user to update MBOM attributes for the organization.
* **updateOrganizationPartAttributes**: Permits the user to update part attributes for the organization.
* **updateOrganizationPartInventoryAttributes**: Permits the user to update part inventory attributes for the organization.
* **updateOrganizationPartKitAttributes**: Permits the user to update part kit attributes for the organization.
* **updateOrganizationPartKitItemAttributes**: Permits the user to update part kit item attributes for the organization.
* **updateOrganizationPartRevisionScheme**: Permits the user to update a part revision scheme for the organization.
* **updateOrganizationPlanAttributes**: Permits the user to update plan attributes for the organization.
* **updateOrganizationProcedureAttributes**: Permits the user to update procedure attributes for the organization.
* **updateOrganizationPurchaseOrderAttributes**: Permits the user to update purchase order attributes for the organization.
* **updateOrganizationPurchaseOrderLineAttributes**: Permits the user to update purchase order line attributes for the organization.
* **updateOrganizationReceiptAttributes**: Permits the user to update receipt attributes for the organization.
* **updateOrganizationRunAttributes**: Permits the user to update run attributes for the organization.
* **updateOrganizationRunStepAttributes**: Permits the user to update run step attributes for the organization.
* **updateOrganizationStepAttributes**: Permits the user to update step attributes for the organization.
* **updateOrganizationSupplierAttributes**: Permits the user to update supplier attributes for the organization.
* **updatePart**: Permits the user to update a part.
* **updatePartAttribute**: Permits the user to update a part attribute.
* **updatePartInventory**: Permits the user to update part inventory.
* **updatePartInventoryAttribute**: Permits the user to update a part inventory attribute.
* **updatePartKit**: Permits the user to update a part kit.
* **updatePartKitAttribute**: Permits the user to update a part kit attribute.
* **updatePartKitItem**: Permits the user to update a part kit item.
* **updatePartKitItemAttribute**: Permits the user to update a part kit item attribute.
* **updatePartProcedure**: Permits the user to update a part procedure.
* **updatePartSubtype**: Permits the user to update a part subtype.
* **updatePartSupplier**: Permits the user to update a part supplier.
* **updatePlan**: Permits the user to update a plan.
* **updatePlanAttribute**: Permits the user to update a plan attribute.
* **updatePlanItem**: Permits the user to update a plan item.
* **updatePlanItemAllocation**: Permits the user to update a plan item allocation.
* **updatePlanReservation**: Permits the user to update a plan reservation.
* **updateProcedure**: Permits the user to update a procedure.
* **updateProcedureAttribute**: Permits the user to update a procedure attribute.
* **updatePurchaseOrder**: Permits the user to update a purchase order.
* **updatePurchaseOrderApproval**: Permits the user to update a purchase order approval.
* **updatePurchaseOrderApprovalRequest**: Permits the user to update a purchase order approval request.
* **updatePurchaseOrderAttribute**: Permits the user to update a purchase order attribute.
* **updatePurchaseOrderFee**: Permits the user to update a purchase order fee.
* **updatePurchaseOrderLine**: Permits the user to update a purchase order line.
* **updatePurchaseOrderLineAttribute**: Permits the user to update a purchase order line attribute.
* **updateReceipt**: Permits the user to update a receipt.
* **updateReceiptAttribute**: Permits the user to update a receipt attribute.
* **updateReceiptItem**: Permits the user to update a receipt item.
* **updateRedline**: Permits the user to update a redline.
* **updateRedlineApproval**: Permits the user to update a redline approval.
* **updateRedlineApprovalRequest**: Permits the user to update a redline approval request.
* **updateRequirement**: Permits the user to update a requirement.
* **updateReview**: Permits the user to update a review.
* **updateReviewRequest**: Permits the user to update a review request.
* **updateRole**: Permits the user to update a role's name.
* **updateRule**: Permits the user to update a rule (i.e. via the API)
* **updateRun**: Permits the user to update a run's information.
* **updateRunAttribute**: Permits the user to update a run attribute.
* **updateRunBatch**: Permits the user to update a run batch.
* **updateRunStep**: Permits the user to update a run step, which includes changing the status of the run step.
* **updateRunStepAttribute**: Permits the user to update a run step attribute.
* **updateRunStepField**: Permits the user to update a run step field.
* **updateRunStepFieldValidation**: Permits the user to update run step field validation.
* **updateRunStepFieldValue**: Permits the user to update the value of a run step field.
* **updateRuns**: Permits the user to update multiple runs.
* **updateSession**: Permits the user to update a checkIn/checkOut event.
* **updateStep**: Permits the user to update step content in a procedure.
* **updateStepApproval**: Permits the user to update a step approval.
* **updateStepApprovalRequest**: Permits the user to update a step approval request.
* **updateStepAttribute**: Permits the user to update a step custom attribute in a procedure.
* **updateStepField**: Permits the user to update a step field in a procedure.
* **updateStepFieldValidation**: Permits the user to update a step field validation in a procedure.
* **updateStepMbomItemAssociation**: Permits the user to update an association between a step and an MBOM item.
* **updateSupplier**: Permits the user to update a supplier and the supplier's contact information.
* **updateSupplierAttribute**: Permits the user to update a supplier's custom attributes.
* **updateTeam**: Permits the user to update a team by adding roles to it.
* **updateUnitOfMeasurement**: Permits the user to update a unit of measurement in the organization settings.
* **updateUser**: Permits the user to update a user's profile and settings. Typically, you can only update your own user profile.
* **updateUserNotification**: Permits the user to update user notifications.
* **updateWebhookHeader**: Permits the user to update a webhook header.
* **updateWebhookReceiver**: Permits the user to update a webhook receiver.
* **updateWebhookSubscription**: Permits the user to update a webhook subscription.


# ION Actions

ION Actions is a powerful tool that allows users to create, write, update, and delete rules governing the behavior of your manufacturing processes using GraphQL.

### LOOK [HERE ](https://manual-v2.firstresonance.io/os/ion-actions)FOR AN UPDATED ION ACTIONS EXPERIENCE

It helps you accomplish everything laid out below but with a in line code editor and streamline UI.

###

### **1. Introduction**

Control workflows (e.g. when users can progress status), set conditions for data validation (e.g. require fields).

### 2. Turn rules on in your environment

First, rules must be enabled in your organization settings in order to use them.

Check that the rules are enabled with the below query:

```graphql
{
  me {
    organization {
      id
      _etag
      settings {
        rules {
          enabled
        }
      }
    }
  }
}
```

If they are not, enable them with this mutation:

```graphql
mutation UpdateOrganization($input: UpdateOrganizationInput!) {
  updateOrganization(input: $input) {
    organization {
      settings {
        rules {
          enabled
          errorState
          errorStateMessage
        }
      }
    }
  }
}
```

With the following input variables (retrieve the `etag` from the first query):

```json
{
  "input": {
    "id": <populate from first query>,
    "etag": "<populate from first query>",
    "settings": {
      "rules": {
        "enabled": true
      }
    }
  }
}
```

### 3. Definition of ION Action Attributes

Here are the definitions of key ION Action attributes:

* **Title:** The title is a visual identifier for the ION Action, shown in toast notifications, and used for internal tracking and logging. It should briefly describe the purpose of the ION Action.
* **Context:** The context is a placeholder that contains the data used in the ION Action's code. It can include model attributes, user roles, issue details, or any other relevant data. It is represented as a JSON string in GraphQL input. An example of a context structure could be:

```python
{
    'changes': {
        'entities': {},
        'issues': {}
    },
    'currentUser': {
        'email': 'alex@firstresonance.io',
        'roles': ['user', 'admin'],
        'teams': []
    },
    'issue': {
        'approvalRequests': {},
        'approvals': {},
        'attributes': [
            {'key': 'Cause Code', 'value': None },
            {'key': 'Component Part', 'value': None },
            {'key': 'Defect Type', 'value': None },
            {'key': 'Department', 'value': None },
            {'key': 'Major Subsystem', 'value': None }
        ],
        'causeCondition': ""
    }
}
```

* **Code:** The code attribute contains the Python-based script that is executed when the ION Action is triggered. It specifies the conditions and actions of the ION Action. If the conditions are not met, a ValidationError is raised.
* **ErrorState:** All active rules will BLOCK the action from occurring if the rule conditions are met. The errorState is a deprecated feature for now, so "ALLOW" or "BLOCK" as an error state are both going to BLOCK the action upon execution of the rule.

### 4. Creating an ION Action with GraphQL

#### **Create an ION Action**

```graphql
mutation CreateRule($create_rule: CreateRuleInput!) {
  createRule(input: $create_rule) {
    rule {
      id
      enabled
      status
      title
      target
      eventType
      context
      code
      errorState
      _etag
    }
  }
}
```

Variables:

```json
{
  "create_rule": {
    "enabled": true,
    "title": "This is the message that shows in the toast banner",
    "target": "ISSUE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "specify the fields for the code to interpret",
    "code": "the python code which runs the logic - must be a single line! (chatGPT helps a lot here)"
  }
}
```

### 5. Updating an ION Action with GraphQL

**Find the rule you seek to update** You'll need the rule's `id` and `_etag` value for the next step

#### Query all rules

```
{
  rules{
    edges{
      node{
        id
        _etag
        title
        ruleType
        eventType
        target
        code
        context
        enabled
      }
    }
  }
}
```

#### **Write the UpdateRule Mutation:**

Write a mutation using the **`UpdateRule`** input type, specifying the rule's `id`, `_etag` and the updates you seek to make (generally the `context`, `code`, or `enabled` values).

```graphql
mutation UpdateRule($update_rule: UpdateRuleInput!) {
  updateRule(input: $update_rule) {
    rule {
      id
      _etag
      enabled
      title
      context
      code
    }
  }
}

```

Query variables:

```json
{
  "update_rule": {
    "id": from step 1,
    "etag": "copied from the step 1",
    "enabled": "true or false"
    "title": "You could modify the title here, or remove this line",
    "context": "overwrite the query, or remove this line",
    "code": "completely overwrite the code, or remove this line"
  }
}

```

**Execute the Mutation:** Run the mutation in the GraphQL Explorer to update the ION Action.

**NOTE:** Every time you update a rule, its `_etag` value will change, so you need to start from step 1 each time you update a rule.

**Example - Video Walkthrough**

{% embed url="<https://www.loom.com/share/bab260ebcc5b464289ea7133d05276f9?sid=0481f86c-d794-4393-b79c-5ae75d2b7b7e>" %}
**Enabling/Disabling a rule through GraphQL**
{% endembed %}

### 6. Deleting an ION Action with GraphQL

This isn't necessary as you can set `enabled` to "false", but to delete an existing ION Action:

1. [**Query the rule** ](#query-all-rules)**to retrieve its `id` and `_etag` value**
2. **Write the DeleteRule Mutation:** Write a mutation using the **`DeleteRule`** mutation, specifying the ION Action `id` and **`_etag`** value.
3. **Execute the Mutation:** Run the mutation in the GraphQL Explorer to delete the ION Action.

#### **Example: Deleting an ION Action**

```graphql
mutation DeleteRule($id: ID!, $etag: String!) {
  deleteRule(id: $id, etag: $etag) {
    id
  }
}

```

Query variables:

```json
{
  "id": <ION_Action_id>,
  "etag": "<current_etag_value>"
}

```


# ION Actions Best Practices

### Overview

The Ion Actions engine enables powerful automation and business logic within ION by allowing users to define rules that respond to object events such as **Work Order updates**, **Issue creation**, or **Part changes**. Rules are written in Python and executed dynamically based on event triggers.

This document outlines best practices for writing, testing, and managing Ion Action rules. Following these guidelines will help ensure reliable behavior, maintainability, and consistency across your automation logic.

***

### 1. Rule Execution and Behavior

#### **Chained Execution**

When multiple rules target the **same object** and **event type** (for example, `Issues Update`), they are **chained together** and executed sequentially. The execution order is determined by internal rule IDs, which are **not user-controlled** and may vary. Because of this, rule order should not be relied upon.

#### **Avoid Top-Level `return` Statements**

If a `return` statement is used at the top level of a rule, the Ion Actions engine will stop executing that rule **and all subsequent rules in the chain**. This can lead to unintended skipping of logic defined in other rules that share the same event target.

**Example (Problematic):**

```python
if issue.status == "Closed":
    return  # ❌ This stops execution of all following rules for this event
```

#### **Use Nested Returns Instead**

To safely control flow within your rule without affecting other chained rules, scope your `return` statements within functions or conditionals. This allows the Ion engine to continue executing subsequent rules.

**Example (Recommended):**

```python
if issue.status == "Closed":
    def handle_closed_issue():
        # Logic specific to closed issues
        return "Handled closed issue"  # ✅ Nested return affects only this function

    handle_closed_issue()
```

***

#### Safely Accessing Context Values

When writing rules, you’ll often chain lookups like:

```python
context.get('part', {}).get('attributes', {}).get('serialNumber')
```

This can easily break if any key in the chain exists but has a value of `None`.\
For example, if `context['part']` is `None`, the call above will return `None` from the first `.get()`\
— causing the next `.get('attributes', {})` to throw a `TypeError`.

The example below shows this:

<pre class="language-python"><code class="lang-python">## Simplified example context dictionary
context = {"part": None}

# ------------------------ #

## Example Bad ION Action Context lookup
<strong>serial_number = context.get('part', {}).get('attributes', {}).get('serialNumber') ## 
</strong># 🛑 Raises: TypeError: 'NoneType' object has no attribute 'get'
</code></pre>

**Recommended Pattern**

Instead, use the following safer pattern:

```python
part = context.get('part') or {}
attributes = part.get('attributes') or {}
serial = attributes.get('serialNumber')
```

This approach safely handles allows you to chain context lookups when the key is missing or the key exists but is `None` . This pattern ensures your ION Action is more resilient when chaining context lookups.

***

#### **Additional Recommendations**

* **Avoid relying on rule execution order.** Each rule should be self-contained and independent.
* **Use variables for decision-making.** Employ local variables or persistent storage to manage conditional logic instead of using `return` to control flow.
* **Test extensively.** Validate behavior across multiple chained rules to ensure predictable outcomes.

***

### 2. Rule Development and Deployment

#### **Version Control and Collaboration**

* As larger organizations scale and have internal software teams we see success in storing Ion Action rules in a **version-controlled repository** (e.g., GitHub or similar).
* Connect your repository to the Ion API to enable direct, auditable deployment of rules.
* Use **pull requests** or **merge reviews** to facilitate peer review, ensuring code quality and alignment with operational standards.
* This approach allows engineers and operations teams to collaborate within familiar development workflows.

#### **Deployment Process**

* Maintain **staging and production environments** for rule deployment.
* Test rules thoroughly in staging before promoting them to production.
* Use automated or semi-automated deployment pipelines to push rules, reducing manual copying and minimizing risk.
* Clearly document rule changes and maintain an internal changelog for traceability.

#### **Governance and Documentation**

* Treat Ion as the **execution platform** for rule logic, while managing source, versioning, and review externally at scale.
* Implement a code review process before merging changes to production.
* Maintain a clear audit trail for compliance and troubleshooting.

***

### 3. Action Context Filters

Filters are allowed in context queries as long as the object supports filtering. Here is an example of a context query that filters for the `Department` attribute on a purchase order:

```graphql
query ($id: ID!) {
  purchaseOrder(id: $id) {
    id
    status
    Attributes(filters: {key: {eq: "Department"}}) {
      value
    }
  }
}
```

This would work fine as long as there are no other actions on the same resource/action (purchase order/update) that also has a different filter on `Attributes` for a purchase order. If you create a new action with this context query:

```graphql
query ($id: ID!) {
  purchaseOrder(id: $id) {
    id
    status
    Attributes(filters: {key: {eq: "Quality Level"}}) {
      value
    }
  }
}
```

An error will be thrown and the actions would not be able to function together. ION Actions merges the context queries for all actions that have the same resource/action so that a single query can be executed.

Solution

The solution is to use an alias on any object where there is a specific filter specified. The above two context queries should be written as:

```graphql
query ($id: ID!) {
  purchaseOrder(id: $id) {
    id
    status
    deptAttr:Attributes(filters: {key: {eq: "Department"}}) {
      value
    }
  }
}
```

```graphql
query ($id: ID!) {
  purchaseOrder(id: $id) {
    id
    status
    qlAttr:Attributes(filters: {key: {eq: "Quality Level"}}) {
      value
    }
  }
}
```

In the code for the action be sure to reference `deptAttr` and `qlAttr` respectively instead of `Attributes`.


# ION Actions examples for Quality

Build custom quality workflows based on the type of issue

### **Open Redlines Prevent Moving Issue Into In Review**

<pre class="language-json"><code class="lang-json">{ 
<strong>  "create_rule": {
</strong><strong>    "title": "Open Redlines Prevent Moving Issue into In Review",
</strong>    "target": "ISSUE",
    "enabled": true,
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "code": "if context.get('issue', {}).get('status') in ['IN_REVIEW'] and context.get('issue', {}).get('redlines') is not None and not all(redline.get('step', {}).get('status', {}) in ['COMPLETE', 'CANCELED'] for redline in context.get('issue', {}).get('redlines')): raise ValidationError()",
    "context": "{ issue(id: $id) { title status redlines { id step { status } } } }",
    "errorState": "BLOCK"
  }
}
</code></pre>

### No Permission To Reopen A Closed Issue

<pre class="language-json"><code class="lang-json">{
<strong>  "create_rule": {
</strong>    "title": "No Permissions to Control Reopening Issues (Need Quality Engineer, Quality Inspector, Reliability Engineer)",
    "target": "ISSUE",
    "enabled": true,
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "code": "if context.get('issue', {}).get('status', {}) in ['IN_REVIEW'] and context.get('changes', {}).get('issues', {}).get('status', {}).get('old', '') in ['resolved'] and not set(context.get('currentUser', {}).get('roles', {})).intersection(set(['Quality Engineer', 'Quality Inspector', 'Reliability Engineer', 'admin'])): raise ValidationError()",
    "context": "{ issue(id: $id) { title status } }",
    "errorState": "BLOCK"
  }
}
</code></pre>

### Issues Cannot be Closed with an Interim Dispositions

```graphql
{
  "create_rule": {
     "title": "Prevent Issue Tickets with Interim Disposition to transition from 'In Progress' to 'In Review'",
     "target": "ISSUE",
     "enabled": true,
     "eventType": "UPDATE",
     "ruleType": "VALIDATION",
     "code": "if context.get('issue', {}).get('status', {}) in ['IN_REVIEW', 'RESOLVED'] and context.get('issue', {}).get('issueDispositionType', {}).get('title', '') == 'Interim': raise ValidationError()",
     "context": "{ issue(id: $id) { title status issueDispositionType { title } } }",
     "errorState": "BLOCK"
  }
}
```

### Can't install a part to aBOM when text custom attribute is not null

```graphql
{
  "create_rule": {
       "title": "Cannot Install on CAPA Part to aBOM",
       "ruleType": "VALIDATION",
       "eventType": "UPDATE",
       "target": "ABOMITEM",
       "enabled": true
       "code": "if any(attr.get('key','') == 'On CAPA?' and attr.get('value',None) is not None for attr in context.get('abomItem',{}).get('part',{}).get('attributes',[{}])): raise ValidationError()",
       "context": "{abomItem(id:$id){part{attributes{key value}}}}",

       }
  }
```

### Can't kit a part while on CAPA

```graphql
{
  "create_rule": {
    "title": "Cannot Add CAPA Part to Kit",
    "ruleType": "VALIDATION",
    "eventType": "CREATE",
    "target": "PARTKITITEM",
    "code": "if any(attr.get('key','') == 'On CAPA?' and attr.get('value', None) is not None for attr in context.get('partKitItem',{}).get('part',{}).get('attributes',[{}])): raise ValidationError()",
    "context": "{ partKitItem(id:$id){ part{ attributes{ key value } } } }",
    "enabled": true
    }
  }
```


# ION Actions examples for Runs and Procedures

#### All Steps Need Dependencies:

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Check if Step has dependencies",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure(id: $id) { id steps{location{name} upstreamStepIds downstreamStepIds } } }",
    "code": "if (context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and any([step for step in context.get('procedure', {}).get('steps', []) if not (step.get('upstreamStepIds') or step.get('downstreamStepIds'))])): raise ValidationError()"
  }
}
```

#### All Child Steps Need Dependencies:

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Check if Child Step has dependencies",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure (id: $id) { id steps { location { id } title isStandardStep steps { title isStandardStep downstreamStepIds upstreamStepIds location { name } } } } }",
    "code": "if context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and any([step for step in context.get('procedure', {}).get('steps', []) if 'steps' in step and len(step.get('steps', [])) > 1 and any([nested_step for nested_step in step.get('steps', []) if not nested_step.get('upstreamStepIds') and not nested_step.get('downstreamStepIds')])]): raise ValidationError()"
  }
}
```

#### All Steps Need a Location

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Check if Step has Location",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure (id: $id) { id steps { location {name} title standardStepStatus steps { title standardStepStatus downstreamStepIds upstreamStepIds } } } }",
    "code": "if context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and [step for step in context.get('procedure', {}).get('steps', []) if step.get('location') is None and step.get('standardStepStatus') is None]: raise ValidationError()"
  }
}
```

#### All Child Steps Need a Location

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Check if Child Step has Location",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure (id: $id) { id steps { location { id } title standardStepStatus steps { title standardStepStatus downstreamStepIds upstreamStepIds location { name } } } } }",
    "code": "if context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and any(nested_step for step in context.get('procedure', {}).get('steps', []) for nested_step in step.get('steps', []) if nested_step.get('standardStepStatus') is None and nested_step.get('location') is None): raise ValidationError()"
  }
}
```

#### A Procedure can only move to ‘In Review’ when the correct reviewers from the correct teams have been added:

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Procedure requires the correct teams to review",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure (id: $id) { type attributes {key value} reviewRequests { id status reviewer { id teams { name } roles { name } } } } }",
    "code": "if context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and [attributes for attributes in context.get('procedure',{}).get('attribute', {}) if context.get('attribute', {}).get('key') == 'Procedure Type' and context.get('attribute', {}).get('value') == 'Build'] and not (any('Responsible Engineer' in team.get('name', '') for reviewer in context.get('procedure', {}).get('reviewRequests', []) for team in reviewer.get('reviewer', {}).get('teams', [{}])) and any('Production' in team.get('name', '') for reviewer in context.get('procedure', {}).get('reviewRequests', []) for team in reviewer.get('reviewer', {}).get('teams', [{}])) and any('Mission Assurance' in team.get('name', '') for reviewer in context.get('procedure', {}).get('reviewRequests', []) for team in reviewer.get('reviewer', {}).get('teams', [{}]))): raise ValidationError()"
  }
}
```

#### Check if the custom attribute ‘Procedure Type’ is filled out

```json
{
  "create_rule": {
    "enabled": true,
    "title": "Procedure Type must be filled out",
    "target": "PROCEDURE",
    "eventType": "UPDATE",
    "ruleType": "VALIDATION",
    "errorState": "ALLOW",
    "context": "{ procedure(id: $id) { status, attributes { key, value } } }",
    "code": "if context.get('changes', {}).get('procedures', {}).get('status', {}).get('new') == 'in_review' and any(attributes for attributes in context.get('procedure',{}).get('attributes', {}) if attributes.get('key') == 'Procedure Type' and attributes.get('value') is None): raise ValidationError()"
  }
}
```


# ION Actions examples for Supply Chain

## Required fields before approval

Mandate that specific PO line attributes are populated before submitting for approval

```
{
  "enabled": true,
  "title": "Purchase line items must have a need date",
  "target": "PURCHASEORDERLINE",
  "eventType": "UPDATE",
  "ruleType": "VALIDATION",
  "errorState": "ALLOW",
  "context": "{ purchaseOrderLine(id: $id) { id needDate } }",
  "code": "if context.get('changes', {}).get('purchaseOrderLines', {}).get('status', {}).get('new') == 'requested' and context.get('purchaseOrderLine', {}).get('needDate') is None: raise ValidationError()"
}
```

Mandate that specific PO header (custom) attributes are populated before submitting for approval

```
{
            "enabled": true,
            "title": "Purchase requires a justification before it can be ordered"
            "target": "PURCHASEORDERLINE",
            "eventType": "UPDATE",
            "errorState": "ALLOW",
            "context": "{ purchaseOrderLine(id: $id) { purchaseOrder {id attributes {key value}}  } }",
            "code": "if context.get('changes', {}).get('purchaseOrderLines', {}).get('status', {}).get('new') == 'requested' and any(attribute.get('key') == 'PO Justification' and not attribute.get('value') for attribute in context['purchaseOrderLine'].get('purchaseOrder', {}).get('attributes', [])): raise ValidationError()"      
 }
```

## Purchase Approvals

We used to rely on ION Actions to enforce purchase order approval levels, but we now have a first class method to do so that is easily understandable and maintained. Check that out [here.](/features/purchasing/purchase-orders/purchase-order-approvals)

### Other Example Rules:

### Receipt line items must have a location

```
{
  "create_rule": {
    "title": "Receipt line items must have a location",
    "ruleType": "VALIDATION",
    "eventType": "CREATE",
    "target": "RECEIPTITEM",
    "code": "if context.get('receiptItem', {}).get('partInventory', {}).get('locationId') is None: raise ValidationError()",
    "context": "{ receiptItem(id: $id) { id partInventory{locationId} } }",
    "enabled": true
    }
}
    
```

### Required fields for part creation

```
{
    "create_rule": {
    "title": "Required fields for part creation",
    "ruleType": "VALIDATION",
    "eventType": "CREATE",
    "target": "PART",
    "code": "if (context.get('part', {}).get('partType') == 'PART') and any([not context.get('part', {}).get('revision') == '', not context.get('part', {}).get('description') == '', not context.get('part', {}).get('trackingType') == '', not context.get('part', {}).get('sourcingStrategy') == '', not context.get('part', {}).get('unitOfMeasure') == '']): raise ValidationError()",
    "context": "{ part(id: $id) { id revision revisionScheme description trackingType sourcingStrategy partType unitOfMeasure { id } attributes { key value } } }",
    "enabled": false
    }
}
```


# ION Importers

The ION Importers provide bulk CSV import for manufacturing data. They give a spreadsheet-like interface where users upload files to create or update records:

* Real-time validation — validates data as users type (parts exist, locations valid, etc.)
* Bulk operations — import up to hundreds of records at once
* Multiple entity types — Parts, Inventory, Suppliers, Locations, Tools, BOMs, Purchase Orders, etc.
* Update or create — Inventory importer can update existing records or create new ones
* Custom attributes — supports custom fields per entity type


# Inventory

ION Inventory Importers enable bulk updates to part inventories via CSV. They handle standard fields (quantity, cost, location, supplier) and custom ION attributes.


# Update

### How to Use the Inventory Update Importer

#### Overview

The Import Inventory (update existing) tool lets you bulk update existing inventory items via CSV. It processes up to 1,000 records and generates a downloadable CSV report with results.

It can be found by navigating to the following page (Parts -> Import -> Import Inventory (update existing):

<figure><img src="/files/DJsMEvIJHoDxGqL3hcuu" alt=""><figcaption></figcaption></figure>

#### Step-by-Step Instructions

**1. Prepare Your CSV File**

Create a file with these columns (all optional except as noted):

Required (at least one):

* Id — Inventory item ID (most specific; recommended)
* OR Part Number + some combination of Revision, Serial Number, Lot Number *(Not recommended - see* [*Known Issues*](/features/ion-importers/inventory/update#known-issues)*)*

Optional fields:

* Revision
* Serial Number
* Lot Number
* Quantity
* Quantity Scrapped
* Unit
* Location
* Supplier
* Cost
* Custom attributes — Any custom fields configured for inventory (save for custom attributes of type File Attachment)

**2. Upload and Validate**

1. Click "Import Inventory (update existing)"
2. Upload your CSV file
3. The importer validates each row as you type:

* Checks that the inventory item exists
* Validates that locations, suppliers, and units exist (if provided)
* Ensures quantity scrapped ≤ quantity
* Shows errors/warnings in real time

**3. Review Validation Errors**

Common errors:

* "No inventory found to update for this record" — Item doesn't exist or lookup fields don't match
* "There are no locations with this name" — Location doesn't exist; create it first
* "There are no suppliers with this name" — Supplier doesn't exist; create it first
* "There are no units with this type" — Unit type doesn't exist; create it first

**4. Submit the Import**

1. Fix any validation errors
2. Click through the importer workflow
3. Processing:

* Records are processed sequentially (one at a time)
* Large imports may take up to 8-10 minutes
* Only one import can run at a time

**5. Review Results**

After completion:

* A success message shows how many records were updated
* A CSV file is automatically downloaded with results:
* Success cases: Shows updated inventory IDs
* Failed cases: Shows inventory IDs and error messages
* Review the CSV to identify any failures (NOTE: in the case of some failures the inventory may have in fact updated - check the specific inventory in ION to check whether it updated prior to re-importing it)

#### Important Notes

* Partial updates: Only include columns you want to update
* Custom attributes: Custom fields are supported and will be updated if provided
* In the case of some failures the inventory may have in fact updated - check the specific inventory in ION to check whether it updated prior to re-importing it
* File size limit: Maximum 1,000 rows per import
* On occasion you may see an error toast pop up in the top lefthand corner during the update. These errors do not block execution of the update - the import will continue, and you will receive a CSV download at the end with all of the errors encountered during upload, as well as the associated part inventory ids.
* If you chose to include a column in the Excel file for upload, it's simplest to have a value in every cell, and have no empty cells (even if the value is not being changed from what it was before)
  * If the column type is a string (e.g. location, supplier, lot number etc), and a cell in the column is empty or blank, nothing will update in ION, even though some of those values (such as location) can actually be set to 'null' in ION.
  * If the column type is a number (like cost, quantity, quantity scrapped), the importer will interpret an empty cell as being a zero value and will set the value to zero in ION.
* Concurrent imports: Only one import can run at a time; if another is in progress, you'll see "Import already in progress" (NOTE: this should only be encountered rarely)
  * Only run bulk updates from a single tab

<figure><img src="/files/bnvaqGb0cJApuAAQfyRq" alt=""><figcaption></figcaption></figure>

NOTE: If you see the 'Import already in progress' display on a large upload, do not click away or re-import. The import is running in the background. When it completes, you'll see the UI with how many records were updated, as well as the CSV export to your downloads.

#### Known Issues

* Even though it looks as if the Part Number and Revision on an inventory can be updated through the importer, in reality they cannot - they are used exclusively to search for a part inventory in lieu of ID
* Updating boolean custom attributes may not behave as expected
* Updating datetime custom attributes in the importer only allows for a DD/MM/YYYY or DD/MM/YY format, and the timezone will be in UTC - not local
* The importer will let you update a part inventory found by Part Number + some combination of Revision, Serial Number, Lot Number (not by ID), even if multiple inventories exist. It will only update one of them, however. *For this reason it is recommended that this method of updating part inventories not be used.*
* (For gov-cloud customers) This importer makes use of a third party library called FlatFile. Table headers are sent to FlatFile's servers. Ensure no export controlled data is on headers.


# Kit Items

The Kit Items Importer allows you to efficiently add or update kit items in bulk from a spreadsheet, making it ideal when you need to add many items to one or more kits at once, update quantities for existing kit items, or avoid manual, line-by-line edits in the UI. Imports are atomic, so if any row contains an error, nothing is changed.

#### Importer Behavior

* **Existing items**: If the kit already has the part (including revision), the quantity is updated. Already kitted inventory will be preserved.
* **New items**: If the kit does not already have the part, a new Kit Item is created.
* **Revisions:** If revision is not filled out, it will select the latest revision for that Part Number
* **Duplicates in the same import**: Duplicate rows for the same Kit+Part within an import returns an error.
* **Atomicity**: Any error prevents all updates and creates. All errors collected from an import will be returned upon a failure.
* **Kit Id**: No new kits are created with this importer. kit\_id is a required value, when left blank the importer will return an error.
* **ION Actions:** Actions with the `PARTKITITEM` target are triggered during the import. If the Action raises a `ValidationError` the standard error toast for Actions will be displayed and the data is not imported.

#### What You’ll See After Import

Following a successful import, a toast will be shown with the number of items imported - including updates and creates - and links to each of the kits affected by the import.

<figure><img src="/files/EDjhSLKzKVGDTn0Iiy4y" alt=""><figcaption></figcaption></figure>

When the importer encounters an error, the changes will be canceled and a table displaying the errors and the rows they occur on will be shown.

<figure><img src="/files/ETcV7ere7rwVCWUQEOCu" alt=""><figcaption></figcaption></figure>




---

[Next Page](/llms-full.txt/1)

