본문으로 건너뛰기
Retail
90 min

Retail Inventory Intelligence

Gather per-branch inventory and competitor pricing data, then build a pricing competitiveness dashboard.

Workshop goals

By the time you finish this Workshop you will have built the following flow by hand inside D.Hub:

  • Imported one scenario into portal in a single command, registering collections, datasets, code, pipelines, ontology, and a dashboard at once.
  • Brought per-branch inventory and per-channel competitor pricing into the same collection and inspected the schemas of both source datasets.
  • Applied the latest competitor prices to the inventory data via the update_competitor_prices pipeline.
  • Toured the ontology — four entities (RI_Product, RI_Branch, RI_Region, RI_Supplier) and three relations.
  • Analyzed the inventory_overview dashboard, which bundles pricing-competitiveness KPIs and per-branch / per-region visualizations.
  • (Optional) Run one cycle of natural-language queries against the graph using the assistant agent.

It's an integrated exercise that ties the collection, pipeline, ontology, and dashboard concepts from the Analyst and Engineer Paths into one real scenario. Recommended time is 90 minutes, stretching to about 100 with the optional section.

Prerequisites

  • An analyst or engineer account with access to D.Hub portal (Editor or higher)
  • ~2 MB of download room for one scenario zip

No terminal, Python, or dhub2-examples clone needed. Finishing the entry-level tutorials Import a scenario zip in one shot and Create your first collection first makes step 1 flow smoothly. Both tutorials are linked directly from the prerequisites card at the top of this Workshop.

1. Import the scenario (10 minutes)

Download one zip and feed it to portal's Import dialog — every asset in the scenario gets registered in a single pass.

retail_inventory_intelligence.zip Download(1.5 MB)

With the zip in hand, go to Collections in the left sidebar. The more (⋯) menu next to the Explorer header (the page title Collections area) has an Import (가져오기) item. Open it, pick the zip you just downloaded, and watch the dialog show upload progress. When it finishes, one collection appears automatically.

Driven by manifest.json, the import creates the following in order:

  1. Collection retail_inventory_intelligence (alias: Retail Inventory Analysis)
  2. Three datasets — retail_inventory, competitor_prices, update_competitor_price
  3. Two code assets — update_competitor_price (python), build_retail_ontology (python)
  4. Two pipelines — update_competitor_prices, ontology_materialization
  5. Ontology — four entities (RI_Product, RI_Branch, RI_Region, RI_Supplier) and three relations (RI_LOCATED_IN, RI_STOCKED_AT, RI_SUPPLIED_BY)
  6. Dashboard inventory_overview
  7. Agent retail-assistant and tool definitions

Right after import, look for retail_inventory_intelligence in the collection tree on the left of portal — that's step 1 done. The collection card header shows the asset count, and the number should match the list above.

2. Explore the data (10 minutes)

Inside the collection, open the Explorer to see how the assets are grouped.

Start with the three dataset cards:

  • retail_inventory (alias: Product Info) — Per-branch product inventory. 27 columns. Eleven branches, item codes, inventory_qty, outbound_qty, inventory_turnover_rate, selling_price_krw_synth, competitor_price_krw_synth, stockout_risk_flag_synth, and latitude/longitude coordinates all in one row.
  • competitor_prices (alias: Competitor Pricing Data) — Competitor price observations by channel, branch, and product. 10 columns. item_code is the join key with retail_inventory.
  • update_competitor_price (alias: Competitor Price Update Result) — The pipeline output. Right after import, this may be empty or contain only sample parquet.

Click each dataset and check:

  • The Schema tab — column names, types, and comments are mapped correctly
  • The Preview tab — the row count is not zero (a few hundred rows for retail_inventory)
  • The Versions tab — v1 is recorded right after import

Next, open the two Code assets (update_competitor_price.py, build_retail_ontology.py). You don't need to read the bodies — glance at the input/output signatures. All you need to keep in mind is that which datasets each code node consumes and emits lines up exactly with the pipeline diagram in the next step.

3. Run the pipeline once (15 minutes)

Now you'll send data through once. In the Pipelines section of the collection, click update_competitor_prices to open the Workflow editor.

You'll see three nodes:

  • Left inputs: retail_inventory, competitor_prices dataset nodes
  • Center: the update_competitor_price code node (python, cdc read mode)
  • Right output: the update_competitor_price dataset node (overwrite write mode)

Click the code node and expand Script preview in the right panel — you'll see a one-liner: left-join retail_inventory and competitor_prices on item_code, then overwrite the competitor_price_krw_synth column with the latest value. The output always needs to reflect current market state, so it's in overwrite mode.

Hit Run at the top to execute once. Progress and step logs flow at the bottom of the run panel, and when it finishes the right-side output node's status flips to fresh. Go back to the collection tree and confirm that the row count and the freshness timestamp on the update_competitor_price dataset have updated.

4. Inspect the ontology (15 minutes)

Now the graph view. Open the Ontology area in the left sidebar and expand the entity list in the retail_inventory_intelligence collection context.

Four entities and three relations should be present.

TypeNameMeaning
EntityRI_ProductProduct master. id = item_code, name, price, PROD_GRP
EntityRI_BranchBranch master. id = branch_code, name, location, latitude/longitude
EntityRI_RegionRegion master. id = region_name (e.g. Seoul Gangnam)
EntityRI_SupplierSupplier master. id = supplier_name
RelationRI_LOCATED_INRI_BranchRI_Region
RelationRI_STOCKED_ATRI_ProductRI_Branch. Carries inventory, turnover, price, and stockout-risk attributes
RelationRI_SUPPLIED_BYRI_ProductRI_Supplier

Click the RI_Product card and check the following in the Builder tab:

  • The backing dataset is set to update_competitor_price (this scenario loads the processed dataset into the graph)
  • The identifier key is id and the display column is name
  • The attribute mapping connects PROD_GRP and price 1:1 to dataset columns

Then open the Graph Explorer. If it's empty, you need to run the ontology_materialization pipeline once more. That pipeline takes update_competitor_price as input and upserts the seven RI_* tables (four entities + three relations). Once it finishes, the Explorer can see the first instances with a one-line Cypher query:

MATCH (p:RI_Product)-[r:RI_STOCKED_AT]->(b:RI_Branch)
RETURN p, r, b
LIMIT 25

When 25 product–branch edges appear in the graph panel, step 4 is complete. Double-clicking a node expands its neighbors — RI_LOCATED_IN reaches the region, RI_SUPPLIED_BY reaches the supplier, all in one step.

The query looks like this:

MATCH (b:RI_Branch)-[:RI_STOCKED_AT]-(p:RI_Product)-[:RI_SUPPLIED_BY]-(s:RI_Supplier)
WHERE b.name = 'Gangnam Finance Store'
RETURN p, s
LIMIT 50

5. Inspect the dashboard (15 minutes)

The final stop is the dashboard. In the Dashboards section of the collection, open inventory_overview (alias: Inventory Intelligence Dashboard). Thirteen widgets are laid out across four rows. Start with the five in the top row.

  • Total inventory (statistic) — SUM(inventory_qty) of update_competitor_price, shown with the EA unit
  • Total outbound (statistic) — SUM(outbound_qty)
  • Average turnover (statistic) — AVG(inventory_turnover_rate) shown as %
  • Stockout risk (statistic) — Count of rows with stockout_risk_flag_synth = 1
  • Average discount rate (statistic) — AVG(discount_rate_synth) * 100

All five are built in SQL Query mode. Click the ⋯ menu on the widget card and choose Edit and you can see the query body as-is. Compare with the Simple mode vs. Query mode toggle from the Analyst Path to see how each applies in practice.

The next row down has visualization widgets:

  • Inventory / outbound by branch — Stacked bar chart. UNION ALL of inventory vs. outbound on branch_name rendered in one chart.
  • Daily outbound trend — Line chart. delivery_date on the X-axis, multi-series by branch.
  • Outbound heatmap by time of day — Intensity map of delivery_time × branch_name.
  • Inventory share by branch — Donut chart, with percentage labels.
  • Inventory detail table — Data table. Page size 10, sorting and search on.

The last row has three pricing-competitiveness widgets. Items priced above competitors (statistic), Average price gap by branch (bar), and Price adjustment candidates (table) all share the selling_price_krw_synth > competitor_price_krw_synth condition. Without running the step-3 pipeline first, the values on these three widgets become meaningless.

6. (Optional) Assistant agent (10 minutes)

If you have time left, call the retail-assistant agent that came with the scenario. In the collection's Agents area, open the Retail Assistant card and start a new session. Run one cycle with these two prompts:

  • "Show the products sold at the Gangnam Finance Store and their suppliers."
  • "List the five branches with the weakest pricing competitiveness versus competitors."

The agent runs Cypher through the ontology_graph_query tool and answers in tables, bar charts, and maps. When the response contains node markers like [[Gangnam Finance Store]], that signals two-way wiring with the Graph Explorer.

This step isn't on the Workshop's critical path, but touching the same graph from human, tool, and LLM points of view at once makes it a strong launch pad for the automation learning round.

7. What comes next (5 minutes)

If you made it here, you've crossed the spot on the Learn site's map where the analysis and visualization of the Analyst Path and the data modeling and pipelines of the Engineer Path meet in a single scenario. Pick the direction that pulls you most and take one more step.

  • Reopen the Analyst Path's chart and DRS lessons and break the Query-mode behavior of this Workshop's widgets down to code.
  • Move to the Engineer Path and go deeper into code nodes and pipeline options. The meaning of cdc read mode and overwrite write mode is the subject of the next round.
  • Write your own domain scenario into dhub2-examples. The Authoring page covers the manifest structure and PR checklist you should follow when authoring a new scenario.

Verification checklist

Self-check whether this Workshop is complete with the five items below.

  • retail_inventory_intelligence appears in the collection tree with seven assets (three datasets, two code, two pipelines — excluding ontology, dashboard, and agent).
  • After running update_competitor_prices, the freshness of update_competitor_price shows the latest timestamp.
  • The dashboard KPI Stockout risk is greater than 0 (the scenario data deliberately includes some stockout flags).
  • Starting from one product in the Graph Explorer, you can expand branch nodes by following the RI_STOCKED_AT relation.
  • The dashboard freshness matches the update timestamp of the update_competitor_price dataset.