openepcis_connector: products and contacts as GS1 master data

The base addon. Products and company contacts are queued on save and published to the catalog behind the GS1 Digital Link resolver; a GTIN can be drawn from your own prefix; the field mapping is data an administrator edits; the form says what a registry still wants before you publish.

openepcis_connector is the addon the other six build on. It depends on product alone, so it installs on an Odoo that has no warehouse at all, and it does one thing: it publishes Odoo's master data — products and company contacts — to the OpenEPCIS catalog behind a GS1-conformant Digital Link resolver, and brings the resulting Digital Link and QR code back onto the form.

Moduleopenepcis_connector
Depends onproduct
InstallsBy hand — this is the one you choose
Talks toThe resolver's HTTP API
Sourceopenepcis-odoo · LGPL-3

What publishing means here

  • Queued on save, delivered in the background. Saving a product never waits for the network. A scheduled action publishes every five minutes; Publish now does it immediately and reports the outcome.
  • Opt-in per record. Nothing leaves the database until somebody ticks Publish to OpenEPCIS on a product or a contact, or runs the mass action on a selection.
  • Onward to GS1 happens on the platform. The connector writes to the catalog; the platform forwards to national registries. The addon never talks to GS1 directly.

Getting a product out

The barcode is the GTIN. Each variant is its own trade item and needs its own. A product without one is one button away from a real number: Draw GTIN takes the next free one from your company prefix.

Figure 1: Draw GTIN takes the next free number from the company prefix. The number is held, not registered, until the record is saved

The number is held, not registered: registration with GS1 cannot be undone, and a number drawn for a form that somebody then abandons would be burnt for good. The resolver keeps it as a candidate until the product is saved, and until then it can be handed back.

The GPC brick lives on the category, once per category rather than per product. Every product in the category inherits it, and the picker searches GS1's classification by name so nobody has to know eight digits by heart.

The form says what a registry still wants. The readiness line names the terms a downstream registry insists on and keeps the list current as you type. It comes from the destination itself — the resolver reports which terms each publishing channel requires — so it is not a guess baked into the addon.

Figure 2: What GS1 Germany still wants, read from the channel's own requirements rather than hard-coded

It informs; it does not block. A passport is filled in over time and by several people, so an incomplete record is published and completed later rather than held hostage.

Tick Publish to OpenEPCIS and save. Within five minutes the state turns to Published and the Digital Link appears, with its QR code on the form and on a printable label.

Contacts as organizations

A passport names a manufacturer, and a manufacturer is a party with a GLN. Company contacts are published the same way products are, anchored on application identifier 417 — the party — rather than 414, the physical location. Both are GLNs; the resolver routes them separately.

Figure 3: A company contact published as a GS1 organization under AI 417

Only companies are published. An individual contact is not an organization, and publishing one would put a person's name and address into a registry.

Organizations also travel the other way. When another system — a second CRM, the resolver's own editor, an import from GS1 — changes an organization in the catalog, a scheduled action brings the change into the contact with that GLN, or creates the contact.

The field mapping is data

Settings → Technical → OpenEPCIS → Field mapping. Each row says which Odoo field feeds which term of the published document, because no two Odoo databases keep a brand in the same place. Dotted paths work on both sides: categ_id.openepcis_gpc_code reads across a relation, brand.brandName writes into a nested object, a [] segment builds a list.

Figure 4: Starting points, editable per row, and marked so an upgrade does not undo your edits

Two shipped rows are worth knowing about. Country of origin points at a field this addon adds, because Odoo's own comes from the Intrastat module, which is Enterprise. Weight is sent as KGM; a database configured in pounds changes the fixed unit on that row to LBR.

Loading an existing catalogue

Settings → Technical → OpenEPCIS → First load. Ten thousand products one HTTP call at a time take an afternoon; the wizard sends them as a single CSV upload, in chunks.

Figure 5: Scope, chunking, and the warnings that go with a create-only endpoint

It is a first-load tool and nothing more. The endpoint behind it creates records and does not update them, so anything the catalog already holds comes back as a duplicate and is left alone, and the bulk format carries only the English name. Everything published later through the ordinary queue carries every language and every mapped field.

Authentication: an offline token

Odoo stores an OIDC offline token — a refresh token issued with the offline_access scope — and mints a short-lived access token from it for every call. No password is kept, nothing long-lived goes over the wire, and access is withdrawn in Keycloak by removing the offline session, without touching Odoo.

The addon consumes a token; it never mints one. Issue it in the OpenEPCIS web interface, under your profile, and paste it into the Offline token field. You configure one URL, the resolver's: the connector reads the resolver's OAuth 2.0 Protected Resource Metadata (RFC 9728) to find which Keycloak realm issues its tokens and discovers that realm's endpoints from there.

Test connection probes the token first and then each thing the resolver will later insist on — the tenant role, the defaultGroup claim, the gs1CompanyPrefix claim — and names whichever is missing, so nobody has to read resolver logs to find out. It also tells "this deployment is older than the feature" apart from "your token is short a claim", which look identical from the outside.

The client settings, the required claims and what was measured against Keycloak are in doc/keycloak.md in the repository.

Limits

One direction for products. Changes made in the OpenEPCIS web interface do not come back to Odoo's products; organizations do, as above.

PUT merges, it does not replace. Clearing a field in Odoo leaves the published value in place, because an absent key means "leave alone" to the catalog.

Some features need a recent resolver. Drawing identifiers, the GPC picker and the readiness list rely on endpoints older deployments do not have. Test connection reports that as "not available on this deployment" rather than as a fault on your side.

There is no GS1 sandbox. A registered identifier is registered for good — GS1 will neither delete nor deactivate a key that has no product data behind it. Before testing against anything but a development deployment, check with your platform operator that dry-run is on, and use the 952 prefix GS1 reserves for exactly this.

Next

The addons that build on this one: lots and serial numbers take the same products down to the instance level, and visibility events report what happens to them.

Last updated: