Products

TL;DR

The catalogue, assembled from Akeneo. A product here is the marketing view; the finance view of the same item arrives separately from NetSuite as ns_items, and the two are joined on the SKU.

A product is a catalogue item: its name, brand, category, attributes, the domains it is live on and the SKUs it is sold as. It comes from Akeneo and is replaced wholesale on every run.

Two views of the same item

products and its tablesns_items
FromAkeneo PIMNetSuite
AnswersWhat it is, what it is called, where it is soldWhat it costs, what it is worth, which GL accounts it books to
Read at/entities/products/entities/products/netsuite

Neither is the other's copy. The calculation rule builder reads products and never ns_items, which is why ns_items.weight and weightunit do not appear as rule filters.

ns_items.weight is a number in an unknown unit. Its unit identifier carries at least four distinct values across the catalogue, so the weights are not even in one unit. Do not convert or compare them until that identifier is mapped.

Where it comes from

app/jobs/akeneo/getproducts.php consumes the akeneo_getproducts batch type, writes the catalogue into _new tables, and akeneo_getproducts_swap swaps them in. Sibling jobs fill the surrounding data with a mixture of upserts and guarded swaps, as described in Akeneo: getbrands.php, getcategories.php, getattributes.php and getproductskus.php.

Every one of those swaps is guarded on row count and refuses when the new table holds fewer rows than the live one, so a truncated Akeneo response leaves yesterday's catalogue in place rather than emptying it.

productids is what keeps a product's id stable. The catalogue table is replaced on every run, so an auto-increment inside it would renumber every product nightly. Instead the job looks the product's cid up in productids, inserts it there if it is new, and uses that id. Anything referring to a product by id therefore keeps referring to the same product.

akeneo/getproductsreset.php cancels the open batches and re-queues a full reload.

Tables

TableHolds
productsOne row per product: name, brand, main category, top-level category, and the flags activated, isengravable, isbundle, inadshop
productidsThe stable cid to id mapping that survives the swap
productdomainsOne row per product per domain: local name, slug, SKU, whether it is activated there, and the live date
productskusThe SKUs a product is sold as
productbrands, productbrandlanguagesBrands and their translations
productcategories, productcategoriestoplevelThe Akeneo taxonomy
productattributes, productattributegroups and their language tablesAttribute definitions, groups and translations; per-product values are in the product JSON attributes
ns_itemsThe NetSuite item: cost, value, quantity on hand, GL accounts
productprices, productstockThe per-SKU feeds, see prices and stock

Most of these are not defined in install.php: they are created by the job that fills them, so a schema change to one is made there.

Where to look, and where to change

/entities/products carries four views:

TabShows
(default)The Akeneo catalogue
NetSuitens_items, the finance view
SKUsThe SKUs per product, with whether each is validated
BundlesThe products marked as a bundle

A product name links to its detail view, which shows one product with its attributes and domains.

Nothing here is editable in CCC. The catalogue is Akeneo's and the item is NetSuite's: correct it upstream and let the next run bring it through. Two related settings are CCC's own and are editable: the private-label brands at /configuration/productprivatelabel and the size options at /configuration/productsizes.

Evidence

Import, the stable id table and the guarded swap from app/jobs/akeneo/getproducts.php and its four sibling jobs. productdomains fields from the INSERT in that job. Views from app/http/entities/products.php and templates/main/entities/products.tpl. The rule builder joining products rather than ns_items, and the weight unit, from AGENTS.md, Models and database. Tables created outside install.php from the same. Basis: code-checked against the current implementation.

About this document
  • Type
    object
  • Status
    active
  • Updated
    2026-09-14
  • Created
    2026-09-13
  • Covers
    entities/products