Integrations & AdvancedERP Integration
Integrations & Advanced

ERP Integration in Jules

How Jules synchronizes data with external ERP systems — fields, entities, sync patterns, and implementation guide.

ERP Integration in Jules

Developer documentation — Jules supports bidirectional synchronization with external ERP systems for contracts, operations, invoices, allocations, and master data.


Table of Contents

  1. Overview
  2. ERP Fields on Entities
  3. Which Entities Support ERP Sync
  4. Sync Mutations
  5. Contract Sync
  6. Invoice Sync
  7. Container-Level Sync
  8. User-Company ERP Sync
  9. Adding ERP Sync to a New Entity
  10. Key Design Decisions

Overview

Jules is designed to coexist with customer ERP systems (SAP, Navision, Sage, custom ERPs). The integration model is:

  • Jules → ERP: mutations trigger data push to the ERP (operations, invoices, allocations, master data)
  • ERP → Jules: the ERP's internal ID and reference values are stored back on the Jules entity via erpId / erpValue

There is no universal ERP connector — each organization configures its own ERP integration at the infrastructure level. Jules exposes the sync hooks (fields + mutations); the actual HTTP/webhook/file-based transport to the ERP is handled by the integration layer.


ERP Fields on Entities

Three fields appear on all ERP-syncable entities:

FieldTypeDescription
erpIdString?The entity's primary identifier in the external ERP (e.g., SAP document number)
erpValueString?A secondary ERP reference value (e.g., ERP internal key, sequential number)
erpCompanyIdString?The ERP's identifier for the counterparty company on this transaction

All three are nullable. Null means the entity has not been synced to the ERP yet.


Which Entities Support ERP Sync

EntityerpIderpValueerpCompanyIdNotes
OperationPurchase and sale operations
OperationQualityPer quality line on an operation
ContractBidirectional sync supported
ContractStreamPer quality stream on a contract
AllocationPer allocation
InvoiceBuy/sell/provider invoices
InvoiceLinePer invoice line item
ContainerInvoicingLinePer container cost element
CompanyCounterparty master data
SiteSite master data
ContactContact master data
BookingFreight bookings
ShipmentShipments

Sync Mutations

Each entity exposes a dedicated sync mutation that can be called to push data to the ERP:

EntitySync mutation
AllocationsynchronizeAllocationToErp
BookingsyncBookingToErp
ContractsynchronizeContractToErp / updateContractErp
InvoicesynchronizeInvoiceToErp
CompanyupdateCompanyErp / createManyCompaniesErp
SiteupdateSiteErp
ContactupdateContactErp
UserToCompanycreateManyUsersToCompaniesErp / deleteManyUsersToCompaniesErp

These mutations typically:

  1. Validate the entity is in a syncable state (e.g., CONFIRMED status)
  2. Push data to the ERP via the configured integration
  3. Store the ERP's response (erpId, erpValue) back on the entity

Contract Sync

Contract synchronization is the most complete bidirectional integration:

Key points:

  • Only CONFIRMED contracts are eligible for ERP sync
  • Each ContractStream (quality line) carries its own erpId
  • Contract renewal via duplication preserves the original ERP reference as a parent reference

Invoice Sync

Invoice sync is typically the highest-priority integration:

  • Invoice sync fires after the invoice reaches CONFIRMED status
  • Each InvoiceLine and ContainerInvoicingLine carries its own erpId for line-level reconciliation
  • The erpCompanyId on the invoice identifies the counterparty in the ERP's chart of accounts

Container-Level Sync

ContainerInvoicingLine has independent ERP sync tracking. This is important for organizations that book costs at the line level in their ERP (common with SAP):

  • Each invoicing line (freight, pre-carriage, agent commission, etc.) has its own erpId
  • This allows partial sync: some lines may be synced while others are pending
  • The sync status of a line is independent of the parent invoice's sync status

User-Company ERP Sync

When an internal user is assigned to manage a counterparty company, this assignment can be synced:

  • createManyUsersToCompaniesErp — push new user-company assignments to ERP
  • deleteManyUsersToCompaniesErp — remove assignments from ERP

This is used in organizations where the ERP tracks which account manager is responsible for each customer/supplier.


Adding ERP Sync to a New Entity

To add ERP sync to a new Prisma model:

Step 1 — Add fields to the Prisma schema

model MyNewEntity {
  // ... existing fields
  erpId         String?
  erpValue      String?
  erpCompanyId  String?
}

Run prisma migrate to apply the migration.

Step 2 — Expose fields in the GraphQL type

Add erpId, erpValue, erpCompanyId to the GraphQL object type in the entity's .type.ts file.

Step 3 — Add update input

Add optional erpId, erpValue, erpCompanyId to the entity's update input type so the sync response can write back to Jules.

Step 4 — Create the sync mutation

// In the entity's resolver
@Mutation(() => MyNewEntity)
@isAuthenticated()
async synchronizeMyEntityToErp(
  @Args('id') id: string,
  @Context() ctx: GqlContext,
): Promise<MyNewEntity> {
  return this.myEntityService.synchronizeToErp(id, ctx);
}

Step 5 — Implement the service method

The service method should:

  1. Load the entity
  2. Validate sync preconditions (status, required fields)
  3. Call the ERP integration (organization-specific transport layer)
  4. Store erpId and erpValue from the ERP response
  5. Return the updated entity

Key Design Decisions

No universal connector

Jules does not ship with a pre-built connector to any specific ERP. The erpId/erpValue fields and sync mutations are the contract surface — the actual transport (REST, SOAP, file exchange, message queue) is configured per organization.

Idempotent sync

Sync mutations are designed to be idempotent. Calling synchronizeAllocationToErp on an already-synced allocation should update the ERP record rather than creating a duplicate.

Status gating

Most sync mutations require the entity to be in a final or confirmed state before syncing. Draft or in-progress entities are not eligible for ERP sync to prevent pushing incomplete data.

Line-level granularity

The ERP sync model goes down to the invoice line and container invoicing line level. This matches the typical ERP requirement for posting individual cost elements to the general ledger.