Integrating with ERP Best Practices

Guide to Connecting ION to your ERP.

We have learned about ERP integration as we have supported integrations with various ERPs, including NetSuite, Epicor, D365, Business Central, Odoo, and Infor. We want to communicate the best practices as you embark on your ERP integration!

If this is your first integration with ION, we highly recommend reviewing our How to create an App with ION guide first to familiarize yourself with ION's API, authentication, and event-driven architecture.

This guide is broken down into general best practices and workflow-specific tips.

Best Practices

#1 Event-Driven Architectures

Traditional schedule-based integrations often rely on periodic data synchronization, which can lead to delays and data inconsistencies. We have found these to be complicated and have far more frequent edge cases that need to be handled. Finally, it means reacting to failures within the integration is delayed based on the schedule, as opposed to being rectified immediately in line while you still have the context of what happened.

By adopting event-driven workflows using webhooks, ION can notify your ERP system immediately when specific events occur, such as the completion of a production run or a quality inspection. This real-time communication ensures that your ERP system has the most up-to-date information, enabling quicker decision-making, fewer edge case handling, and enhanced operational responsiveness. ION supports Webhooks to facilitate real-time event information delivery. If you don't need this information synced into your ERP so often, we recommend creating a queue with your integration provider that stores the updates from ION's event-driven architecture before uploading that into your ERP system on a schedule-driven basis.

Workflow Tips

#1 Synching aBOMs from ION to ERP

aBOM installations can be assessed on parts inventory associated with completed runs using a query similar to this:

GQL Query:

query (
    $filters: RunsInputFilters
  ) {
    runs(
      filters: $filters
    ) {
    edges {
      node {
        title,
        partInventory {
          part {
            partNumber
          }
          quantity
          buildRequirements {
            abomInstallations {
              quantityInstalledPerParentPartInventory
              partInventory {
                location {
                  id
                }
                part {
                  partNumber
                }
              }
            }
          }
        }
      }
    }
    pageInfo {
      hasNextPage
      endCursor
    }
  }
}

GQL Variables (Note: These will be different for an ERP integration)

{
  "filters": {
     "id": {
        "in": [2200]
     }
  }
}

Such a query will return a JSON object with the following structure:

{
  "data": {
    "runs": {
      "edges": [
        {
          "node": {
            "title": "Run - Create Assembly Part One",
            "partInventory": {
              "part": {
                "partNumber": "Assembly Part One"
              },
              "quantity": 3,
              "buildRequirements": [
                {
                  "abomInstallations": [
                    {
                      "quantityInstalledPerParentPartInventory": 2.4,
                      "partInventory": {
                        "location": {
                          "id": 262
                        },
                        "part": {
                          "partNumber": "Component Part One"
                        }
                      }
                    },
                    {
                      "quantityInstalledPerParentPartInventory": 2.6,
                      "partInventory": {
                        "location": {
                          "id": 269
                        },
                        "part": {
                          "partNumber": "Component Part One"
                        }
                      }
                    }
                  ]
                },
                {
                  "abomInstallations": [
                    {
                      "quantityInstalledPerParentPartInventory": 3,
                      "partInventory": {
                        "location": {
                          "id": 263
                        },
                        "part": {
                          "partNumber": "Component Part Two"
                        }
                      }
                    }
                  ]
                }
              ]
            }
          }
        }
      ],
      "pageInfo": {
        "hasNextPage": true,
        "endCursor": "YXJyYXljb25uZWN0aW9uOjA="
      }
    }
  }
}

To assess all of the abom installations on the part inventory created during the run, multiply the quantity produced on line 12 by the quantityInstalledPerParentPartInventory for each installed part inventory (lines 17, 28 and 43 respectively). NOTE: Lines 17 and 28 reference the same part but installed from inventory in two different inventory locations.

For this particular run that created three of Assembly Part One, in total:

  • 15 of Component Part One were required (2.4 * 3 + 2.6 * 3)

  • 9 of Component Part Two were required (3 * 3)

Last updated

Was this helpful?