COGS Onboarding Worksheet — MIZOKI Signal for Shopify (P1)

Status: v1.0 (2026-08-11) · P1 workstream zero (INTEGRATION PROMPT v2.3 F6) · For ERP-less merchants; canon: docs/product/SIGNAL_SHOPIFY_MASTER_v4.md §2.1 (cost side) and §2.5 (NCM-v1 terms). Machine template: cogs_worksheet_template.csv.

Why this exists

NCM-v1 (services/measurement-rails/ncm_v1.py) refuses to guess costs: an order with no COGS components or an unreconciled bundle is rejected, not estimated. This worksheet is how a merchant without an ERP supplies the per-variant truth once, so every order after that computes honestly. Bundle/kit distortion is a known Shopify analytics failure mode — the worksheet forces bundle decomposition up front.

How to fill it (one row per sellable variant)

Column NCM-v1 term What to enter Honest default when unknown
variant_id — Shopify variant ID (the component variant, not the bundle listing) required — no default
sku — Your SKU for the variant required
landed_unit_cogs COGS Supplier cost + inbound freight + duty, per unit, in store currency leave blank — the row is excluded and flagged, never guessed
is_bundle COGS true if this listing sells a kit of other variants false
bundle_components COGS For bundles: component_variant_id:qty pairs separated by ; (e.g. 123:2;456:1). Component rows must exist with their own landed_unit_cogs. required when is_bundle
pick_pack_cost F 3PL pick/pack fee per unit (your 3PL rate card) fulfillment default row (below)
dimensional_surcharge F Oversize/dimensional shipping surcharge per unit, if any 0
return_rate_pct E[RL] Trailing 12-month return rate for the variant (or category) in percent category default row, labeled
return_unit_cost E[RL] Freight-in + inspection labor + restock or markdown loss per returned unit category default row, labeled
notes — Free text (supplier, season, effective date) empty

Store-level defaults sheet (second block of the CSV): payment/platform fee percent (S), default pick/pack, category-level return defaults. Store-level promo cost (P) is not on this sheet — promos pro-rate from Shopify discount data per order.

Rules the worksheet enforces (same rules the code enforces)

  1. Bundles decompose or are rejected. Every bundle_components variant must have its own costed row; quantities must reconcile to the bundle quantity.
  2. Blank beats guessed. A blank landed_unit_cogs excludes the variant from NCM and shows up in the coverage report; an invented number would silently poison every margin figure downstream.
  3. Currency is the store currency everywhere. No mixed-currency rows.
  4. Effective-dated updates, never edits-in-place once live: append a new row with a later effective date in notes; history stays reconstructable.
  5. Values entered here are merchant-confidential inputs — they feed NCM-v1 computation and never leave the tenant boundary (fleet-integrity rules: no cross-merchant visibility).

What happens next (P1 flow)

Worksheet → validated import (rejects rule violations with row-level reasons) → per-variant cost table → OrderEconomics per order → NCM-v1. The validated-import step is built (P1 build plan item C1): services/measurement-rails/cogs_import.py parses exactly this CSV shape — its suite parses the repo template file directly, so a change to either side fails the build instead of drifting silently.

← All docsView source on GitHub →