Supply Lens

How Supply Lens matches codes

How Supply Lens turns the codes on a Document into your Products, Parties, Locations and units, which identifier wins when several apply, and how a line's unit of measure is decided.

Every record in your master data carries identifiers: a type (such as SKU, GTIN-13, GLN or Unleashed Customer Code) and a value (such as HT-HOUSE-250). This page explains how Supply Lens uses them in both directions:

  • Inbound (matching): turning a value on a Document into one of your records, such as a SKU into a Product or a GLN into a Party.
  • Outbound (looking up): turning one of your records back into the value another system expects.

What happens when a Document arrives

Rendering diagram...
  1. Cross-reference matches each code on the Document (products, parties, locations, units of measure and so on) to your records.
  2. Enrichment fills in what cross-reference leaves open, using your defaults: first the header (for example the customer, from the ship-to), then each line (for example the unit of measure).
  3. The two steps repeat while enrichment keeps changing something. A Document still changing after ten passes fails, as a likely misconfiguration.
  4. Mappings then run and target data is sent.

On the Document, a green tick beside a party or line shows it was matched to one of your records. Click it to open the record.

Filter, then rank

When more than one identifier could apply, Supply Lens always works in two steps.

1. Filter. Each scope on an identifier (such as Party, country, currency or Integration) is either empty, so the identifier applies everywhere, or set, so it applies only in that context. An identifier survives only if every scope it sets matches the Document. An identifier scoped to a different Party, currency, country or Integration is thrown away, not just ranked lower.

2. Rank. The survivors are compared one scope at a time, in a fixed order for each kind of record. At each step, an identifier that sets that scope beats one that leaves it empty. The first step that separates two identifiers decides, and later steps aren't considered.

So the order is strict, not a points system: an identifier scoped only on the first step beats one scoped on every other step combined.

If the Document has no value for a scope (no customer has been matched yet, say), only identifiers that leave that scope empty survive.

The ranking order for each kind of record

RecordRanking order, highest priority first
ProductParty → country → currency → Integration
PartyYour organisation's own (not shared) → Integration → Integration type → Live or Test → country → currency
LocationYour organisation's own (not shared) → Integration → Party (customer)
Tax codeYour organisation's own (not shared) → country → order number
Unit of measure, currency, country, shipping companyYour organisation's own (not shared) → order number

Notes on the table:

  • Products always belong to your organisation, so "own or shared" never separates them.
  • Parties can be shared across organisations, so your own identifier beats a shared one before anything else. An identifier scoped to one Integration beats one scoped to every Integration of that type, and either beats one with no Integration scope.
  • Locations rank Integration before Party, the reverse of Products. The Party scope is what lets one Location carry a different ship-to code for each customer; outbound, a code scoped to another customer is filtered out and never sent.
  • Code lists (tax codes, units, currencies, countries, shipping companies) are shared reference data with your own identifiers alongside. They have no Party, currency or Integration scope. Instead, each identifier has a position in an order, set by reordering identifiers on screen, and the lowest order number (highest in the list) wins. This matters most outbound: a unit with several codes of one type sends the one highest in the order. Tax codes add one step, country, so a tax code identifier for the Document's tax country beats one that applies anywhere.

Which context is used

ScopeTaken from
IntegrationInbound: the source Integration the Document came from. Outbound: the target Integration the data is going to. So an Integration-scoped identifier applies to Documents received from it, and to data sent to it.
PartyThe Document's counterparty, the same in both directions. For a Product or Location this is normally the customer on a sales Document.
Integration type and Live or Test (Parties only)The same Integration as above: its type, and whether it is in its live or test state.
Country and currencyThe Document's country and currency. For a tax code, the country the Document's tax is assessed in.

Worked example: which Product code is sent

A Product has three identifiers of the same type. A shipment for customer Acme, in GBP, is being sent to Shopify.

RowValuePartyCurrencyIntegration
1WIDGET(none)(none)(none)
2WID-GBP-SHOP(none)GBPShopify
3ACME-W1Acme(none)(none)
  • For Acme: all three survive. Row 3 wins at the first step, Party, even though row 2 is scoped on two things.
  • For a different customer: row 3 is filtered out. Row 2 wins on currency.
  • In EUR for a different customer: rows 2 and 3 are filtered out, so row 1, the unscoped default, is used.

Ties and ambiguous matches

If two identifiers survive every step level with each other:

SituationWhat happens
Both belong to the same record (duplicate rows)One of them is used and there is no error. Outbound, if their values differ, which value is sent is effectively arbitrary, so give one a narrower scope or, on a code list, a higher position.
They belong to different records, on an inbound matchThe match is ambiguous. Supply Lens reports the identifier as an error naming both records, rather than picking one.
An outbound lookupIt is already for one known record, so one of its tied rows is used.

An inbound tie between different records, such as two Products both claiming the SKU WIDGET with the same scope, means the data is wrong, so Supply Lens won't guess.

Several identifiers on one line

A line often carries more than one identifier, such as a SKU and a barcode. Supply Lens tries every type and value provided and takes the winner across all of them using the same ranking. The identifier type is not part of the ranking: a Party-scoped barcode match beats an unscoped SKU match, and an unscoped SKU and an unscoped barcode that lead to different Products are a tie, reported as ambiguous.

How a line's unit is decided

A Product identifier can say which unit of measure it stands for. A GTIN-13 usually identifies the consumer unit and a GTIN-14 the case, so when a partner orders "3" of a GTIN-14 and sends no unit, they mean three cases. The identifier's unit is informational: it plays no part in which Product a value matches or which identifier is sent. Its only effect is to set the unit of an inbound line's quantity, during enrichment.

When it runs

Enrichment only works out line units when all of these are true:

  • your organisation has a default single unit of measure configured;
  • the Document has lines: Credit, Goods Inbound, Goods Inbound Receipt, Invoice, Order, Order Change, Purchase Credit, Purchase Invoice, Purchase Order, Shipment, Warehouse Order or Warehouse Shipment;
  • your organisation has at least one Product.

The order of checks

For each line whose Product has been matched but whose unit hasn't, Supply Lens stops at the first answer:

Rendering diagram...
  1. The identifier's unit, if the sender gave no unit and no traded unit size, and the line was matched on an identifier that carries a unit.
  2. The Product's default unit for the source Integration.
  3. The traded unit size, if given: a size of 1 means your organisation's single unit; a larger size means the unit whose conversion on the Product holds that many singles. If there is none, the Document fails.
  4. The Integration's default unit, if the Document has a source Integration.
  5. The Product's default unit.
  6. Otherwise the line is left unresolved.

Once the unit is known, any price for a line with an ordered quantity is looked up in that unit.

When the identifier rule stands aside

It only fills a gap. It does nothing when the line's unit is already resolved; when the sender gave a unit, even one that didn't match; when the line has a traded unit size; or when the line carries no identifier values to compare.

Which identifiers count

  1. Only the Product's identifiers that carry a unit take part.
  2. Their type and value must equal a value on the line.
  3. Their scope must fit the Document (customer, country, currency, source Integration), as in matching.
  4. Of those, only the ones at the most specific scope count, in the Product order: Party, country, currency, Integration. A GTIN-14 scoped to the customer outranks an unscoped one. A more specific identifier with no unit doesn't hide a less specific one that has a unit.

If they all imply the same unit, the line takes it. If they disagree (typically because the line sent both the GTIN-13 and the GTIN-14), none is used: a warning is logged and the line falls through to the defaults.

Worked examples

A Product has a GTIN-13 marked Unit and a GTIN-14 marked Case, and defaults to Each. The organisation has a default single unit.

The line sendsResultWhy
GTIN-14, quantity 3, no unit3 CaseOne match, which implies Case
GTIN-13, quantity 3, no unit3 UnitOne match, which implies Unit
GTIN-13 and GTIN-14, no unit3 EachThey disagree, so a warning is logged and the defaults decide (here the Product's own, assuming the source Integration has no default unit)
GTIN-14 with unit PCENot from the identifierThe sender gave a unit
GTIN-14 with a traded unit size of 1The organisation's single unitA traded unit size takes the conversion route (assuming no Product default for the source Integration, which would come first)
SKU only, no unitDefaults as beforeThe SKU carries no unit

If the GTIN-14 were scoped to customer Acme, the first row would give Case only on Acme's Documents; for anyone else the GTIN-14 is out of scope and the defaults decide.

Things to know

  • The customer can be filled in during the same pass. Enrichment fills the header (for example the customer, from the ship-to) before the lines, so a customer-scoped identifier's unit can apply in the same pass.
  • Outbound only sees the result. Sending uses the line's resolved unit; it never reads the identifier's unit directly.
  • A disagreement can repeat its warning on later passes if no default resolves the line either.
  • Matching and choosing which identifier to send work exactly the same with or without a unit.

Log messages

MessageMeaning
Resolved unit of measure for line number N as X from the product identifier it was matched onThe identifier's unit was used.
The product identifiers line number N was matched on imply different units of measure (…), so none of them has been appliedThe identifiers disagreed; the line fell through to the defaults.

Setting an identifier's unit in bulk

The Product import and export carry two kinds of unit column besides the fixed Unit of Measure column:

ColumnHoldsExample
<identifier column> uomThe unit the identifier in the matching column stands forid gtin-14 uom, id gtin-14 (country: GB) uom
Unit of Measure (integration: <key>)The Product's default unit for one IntegrationUnit of Measure (integration: shopify-main)

Both take unit names, and a name that matches nothing comes back for mapping. A blank cell changes nothing unless the import is set to clear blank values. A uom column never creates an identifier: a unit for an identifier the Product doesn't have is skipped and counted in the result. See Import Products in bulk.