Skip to content

Map Products

Map raw rows from an uploaded file into the scenario's products table: every product or SKU your demand, supply, lanes, flows and recipes refer to, and the product group, the class, each one belongs to.

When to use this

  • Any row of your scenario names a product: demand, supply, a lane, a flow, a handling or inventory rule, a recipe
  • You want a mistyped product name caught when the scenario is built, not discovered as unmet demand after a run
  • You want to record each product's class or tags, so that a lane, a unit conversion or an Add Constraint rule can cover the products of a class or with a tag

What you need

  • An upstream Import Data node (or operation node) carrying one row per product
  • At minimum, a column with each product's name, spelled exactly as the other files spell it
  • Optionally, a product group for each product, its class, such as Chilled or Frozen
  • Optionally, a description for each product
  • Optionally, tags for each product, such as Food or Key Wines: as a Tags column, or as a second table wired into Tags

Field mapping

Fields are matched by name unless you set them. When the workflow runs, every field you have not set a column for is matched against the headers listed below, case-insensitively and ignoring spaces around the header, and a space inside your header reads as an underscore, so Site Name matches site_name. Setting a column for one field fixes that field only; the others keep following your file's headers, so a renamed column is still found. A required field that no column supplies — no header matched, or you set none or one your table lacks — is reported once, with the headers your table does have.

Set mappings in the node's panel. Connect an upstream table and select the mapping node. A field matched by name is marked Matched by name; pick a column to set it yourself, and Match by name puts it back. Match all by name clears every field you set. Required fields without a match are marked in the panel.

Reshape rows in a Script first. A mapping node only says which column is which field. To drop rows, recode values, or split or combine columns, connect a Script node before it and map the columns the Script returns.

Field Type Required Example What it is Auto-detected headers
Product text Yes Riesling 0.75 Product or SKU name (unique identifier). Every product a row names elsewhere in the scenario must be listed here. product, sku, item, material, product_id, product_name
Product Group text No Chilled The product's class, such as Chilled or Frozen. product_group, group, category, product_category, product_family, family
Description text No White wine, 0.75 l bottle Free-text description of the product. description, product_description, desc, name_long
Tags text No Food; Key Wines The product's tags, separated by semicolons, such as Food; Key Wines. A filter tests one with "Food" in product.tags. tags, tag, labels, product_tags

Tags field mapping

The table wired into Tags is mapped in its own section of the panel, below the node's own fields and in the same way: a field you have not set a column for is matched by name against that table's headers.

Field Type Required Example What it is Auto-detected headers
Tag text Yes Key Wines The tag, such as Food or Key Wines. A filter tests it with "Food" in product.tags. tag, tags, label, assortment, collection
Product text Yes Riesling 0.75 The product the tag is on. Every product must be one of Map Products' own. product, member, sku, item, material, product_id, product_name

How it works

Each upstream row produces one product record. The records flow to a downstream Create Scenario node, which collects everything and writes the scenario.

The products table is the scenario's list of its products. Every other table refers back to it by name, and only to the names it holds: a row naming a product that is not there stops Create Scenario, which names the table, the rows and the unknown names. A product is never added to the list because a row happens to mention it, so Riesling 0.75 in one demand file and Riesling 0,75 everywhere else is reported rather than becoming a second product with demand and no supply.

ALL is the one exception. On a lane, a handling rule, a handling state row, an inventory rule or a unit conversion, ALL (in capitals) means every product in this list, and it is not looked up as a product. That makes ALL reserved: no product may be named ALL, in any capitalisation, and a row that has to name one product cannot use it. A lane or a unit conversion may also write a filter over products, such as product.product_group == "Chilled" or "Key Wines" in product.tags, and then applies to each product the filter matches (see Map Lanes and Map Units & Conversions).

Every row has to name its product: a blank product is refused, naming the table and the rows. Write ALL instead where the row applies to every product and the column allows it.

Network Optimization, Cost to Serve, XYZ Segmentation, Center of Gravity and Consolidate Shipments check the scenario against these rules before they run. A saved scenario that breaks one — for example, one whose rows name products and that has no products — stops the step with the same message Create Scenario gives, saying to add Map Products to the workflow that builds the scenario and run it again.

Tags

A tag is a word you put on a product to say what it is part of, such as Food, Key Wines or Launch Range. A filter then selects by tag, as in "Food" in product.tags, on a lane, a unit conversion or an Add Constraint rule, so a product you tag later is covered on the next run. A product may carry any number of tags. Where a product's class is already its Product Group, filter on that instead: product.product_group == "Chilled".

Tags come in one of two ways, or both:

  • A Tags column on the products table, mapped to the Tags field. Each cell holds the product's tags separated by semicolons, such as Food; Key Wines. Spaces around each tag are ignored. A cell with an empty piece, such as Food;;Key Wines or a trailing ;, is refused rather than read as fewer tags. A blank cell means no tags.
  • A Tags table wired into the node's second input, Tags, in long form: one row per tag and product, a tag in one column and a product in the other. Its rows are added to the Tags column of the product each row names. Left unwired, the node maps products only, exactly as without it.

Either way the scenario stores each product's tags once, in its Tags column, so every node that reads the scenario sees the same ones. Tags are compared exactly as written, capitalisation included: Food and food are two tags.

A Tags table is refused, with the rows and the fix named, when:

  • a row lacks its tag or its product
  • a row names a product this node does not map, usually a typo

Workflow wiring

flowchart LR
    n1["Import Data (products.csv)"] --> n2["Map Products"]
    n3["Import Data (locations.csv)"] --> n4["Map Locations"]
    n5["Import Data (demand.csv)"] --> n6["Map Demand Policy"]
    n7["Import Data (lanes.csv)"] --> n8["Map Lanes"]
    n2 --> n9["Create Scenario"]
    n4 --> n9
    n6 --> n9
    n8 --> n9

To add tags in long form, connect a second Import Data node carrying the Tags table to the Tags input of Map Products. The first table you connect is the data to map; the Tags table goes to the Tags input.

Common mistakes

  • Spelling a product differently across files. Riesling 0.75, riesling 0.75 and Riesling 0,75 are three different products. Use one spelling in every file, and list exactly that spelling here.
  • Listing only the products you sell. Components a recipe consumes are products too, and every one a recipe or a supply row names must be in this list.
  • Wiring the Tags table into the first input. It is then read as products. The Tags table goes into Tags.
  • Separating tags with commas. Food, Key Wines is one tag with a comma in it. Separate tags with semicolons: Food; Key Wines.
  • Naming a product ALL. ALL means every product, in any capitalisation; rename the product.
  • Wiring Map Products straight into an analysis node. It has to flow through Create Scenario first. The scenario is what analyses read from.

Messages this node can show

The table this node makes is checked again with the rest of the scenario when Create Scenario assembles it: see messages about the scenario.

A run gives this node 5 minutes. A node that takes longer stops with Time limit reached.

Like every node, it can also stop on the checks before a run and the run's limits.