Field Mapping — Navision, Ergonode and the New Backend (ZWE-391)¶
Pending Florian's review — not yet approved
This mapping has not been reviewed or signed off by Florian yet. Treat everything below as a draft proposal, not an approved source of truth, until that review happens and this notice is removed.
ZWE-391
Maps every real GetProduct field (Core Webshop Endpoints, NAV Field Inventory) to the new backend data model, alongside Ergonode's confirmed attribute codes (ZWE-496) and the backend's actual schema (products/product_attributes/orders). Needs review and approval from Florian before it's final.
Answering the open questions¶
1. Which system leads per field?¶
| Data | Leads | Why |
|---|---|---|
| Price | Navision | GetSalesPrice/GetProduct.PriceIncludingVAT — real-time ERP pricing, not editorial |
| Stock | Navision | StockQuantity/StockQuantity2/GetRealStock — live inventory, changes constantly |
| Barcode | Navision | LSItemBarcodes[] — ERP is the barcode master |
| Article number | Navision | ItemNo is NAV-native; Ergonode's artikelnummer attribute mirrors this same value rather than originating it — see linking key below |
| Status / orderability | Navision | LSItemStatusLink.StatusCode / Blocked / NoStockPosting — already the source for NavStatusNormalizer (ZWE-486) |
| Title, description, images, category structure | Ergonode | Editorial/marketing content — matches the "Ergonode is the PIM" restructure note and the naam/product_media attributes confirmed in ZWE-496 |
Colour, size, material, gender (kleur/maat/materiaal/sekse) |
Ergonode | Confirmed real Ergonode attribute codes (ZWE-496, from the real CSV export) — customer-facing product attributes, editorially maintained |
| Brand | Ambiguous, flag for Florian | NAV has Brand/BrandDescription as a code+description pair; Ergonode has a merk attribute. Unclear whether these use the same taxonomy/codes — needs checking before deciding which leads |
2. NAV fields with no backend equivalent¶
| Field | Recommendation | Reasoning |
|---|---|---|
Cost / LastCost |
Drop | Internal purchase cost, not customer-facing; not part of the webshop's canonical product model |
SeasonCode |
Drop | Ergonode's collectie attribute already covers seasonal/collection grouping — redundant |
ItemCategoryCode / ProductGroupCode |
Drop | Category structure is already sourced from Ergonode (ZWE-496); these NAV codes would be a second, conflicting category source |
VendorItemNo |
Drop | Vendor's own SKU, not customer-relevant; purchasing/admin concern only |
Published |
Extend | Not currently wired anywhere — but products.status (ProductStatus::Online/Offline) has no real source today. Worth wiring NAV.Published into it rather than leaving products.status unset by any real data |
LSItemVariant.ColourCodeVendor |
Drop | Vendor's raw colour code; Ergonode's kleur attribute is the customer-facing equivalent |
3. How is a product identified and linked?¶
NAV.ItemNo is the real linking key across all three systems:
- Navision:
ItemNo(e.g.003027608) - Ergonode: the
artikelnummerattribute — confirmed via the real bulk CSV export (ZWE-496) to hold this exact same value - New backend:
products.reference— should hold this same value, but currently doesn't
Known gap, already flagged on ZWE-396
The ZWE-396 seeder currently populates products.reference with slug-style values (e.g. SCARPA-RIBELLE-RUN-GTX), not real NAV ItemNo values — flagged as a known limitation in that PR. For the real sync-then-local-query flow (ZWE-495) to actually link a product to its NAV/Ergonode source, products.reference needs to be populated with the real ItemNo once real data replaces the seeded demo catalog.
Variant-level: NAV.LSItemVariant.Code is the equivalent linking key for variants, and already flows through the new backend's order_lines.variant_code field (used directly in NavOrderPayloadBuilder, ZWE-423).
4. Fields needing a check with the ERP administrator¶
PricevsPriceIncludingVATonGetProduct— isPricea genuinely separate excl-VAT list price, or simplyPriceIncludingVATdivided by the VAT rate? Not confirmed either way from the WSDL alone.StockQuantity(item) vsStockQuantity2(variant) vsGetRealStock's single value — this is the same terminology gap already flagged on ZWE-494 ("real/free/wholesale stock" not found as-is in the schema) — cross-referencing here rather than re-asking.- Brand taxonomy — see question 1 above.
Resolved: OrderStatus anomaly
Previously flagged here as open — confirmed by Jasper. SubmitOrder always sends OrderStatus=30 (Complete); NAV computes/overrides the status internally afterwards (its own picking/invoicing workflow), so the 20 (Processing) seen on a real queued order is NAV's own value, not POS-originated. The status sent by the webshop is advisory only. See the full explanation on Core Webshop Endpoints. This leaves a real decision for the backend: persist/act on NAV's OrderStatus/ShippingStatus, or keep reacting only to PaymentStatus as the legacy site does today — not yet decided.
Mapping table¶
NAV field (GetProduct) |
Target (backend) | Transformation | Source of truth |
|---|---|---|---|
ItemNo |
products.reference |
direct — once real data replaces the seeded catalog, see the gap noted above | Navision |
Name / ShortDescription |
product_attributes (Title) |
direct, but see Q1 — Ergonode's naam should lead here in practice |
Ergonode |
PriceIncludingVAT |
product_attributes (Price) |
direct | Navision |
Price |
(not mapped) | see Q4 — ambiguous, needs ERP admin confirmation before mapping | Navision |
StockQuantity (item) |
product_stock.stock (item-level rows) |
direct, pending Q4 clarification | Navision |
LSItemVariant.StockQuantity2 |
product_stock.stock (variant-level rows) |
direct, pending Q4 clarification | Navision |
Blocked (item) / LSItemVariant.Blocked (variant, string) |
NavStatusNormalizer output → orderability |
already implemented, ZWE-486 | Navision |
NoStockPosting |
NavStatusNormalizer::ignoresStock() |
already implemented, ZWE-486 | Navision |
LSItemStatusLink.StatusCode |
NavArticleStatus enum |
already implemented, ZWE-486 (handles GEBLOKKEER truncation) |
Navision |
Brand / BrandDescription |
brands.name / brands.slug |
pending Q1 - Ergonode's merk may supersede this |
Flagged - see Q1 |
LSItemVariant.Code |
order_lines.variant_code (and equivalent on product_attributes/product_stock variant rows) |
direct, already used in NavOrderPayloadBuilder (ZWE-423) |
Navision |
LSItemVariant.Description |
order_lines.size / order_lines.colour (parsed) |
needs a parsing rule - variant descriptions observed as e.g. L/125 CANARY (size/colour combined) |
Navision (raw), parsing TBD |
LSItemBarcodes[] |
order_lines.barcode |
direct | Navision |
Ergonode naam |
product_attributes (Title) |
direct | Ergonode |
Ergonode artikelnummer |
products.reference (linking key) |
must match NAV.ItemNo exactly |
Ergonode (mirrors Navision) |
Ergonode sekse / kleur / maat / materiaal / waterdicht / collectie |
product_attributes (respective) |
direct, per the EAV pattern already used in DemoProductSeeder |
Ergonode |
Ergonode product_media |
media (Spatie Media Library images collection) |
direct | Ergonode |
Cost / LastCost |
— | dropped, see Q2 | — |
SeasonCode |
— | dropped, see Q2 (superseded by collectie) |
— |
ItemCategoryCode / ProductGroupCode |
— | dropped, see Q2 (superseded by Ergonode categories) | — |
VendorItemNo |
— | dropped, see Q2 | — |
Published |
products.status |
extend — not currently wired to any real source, see Q2 | Navision |
LSItemVariant.ColourCodeVendor |
— | dropped, see Q2 (superseded by kleur) |
— |
Related pages¶
Core Webshop Endpoints NAV Field Inventory Legacy Integration