Categories
Three category trees exist side by side: the live Akeneo taxonomy, NetSuite's own, and a retired one kept for comparison. Reports group on the Akeneo top-level category.
A category classifies a product. CCC holds more than one tree because the systems it reads from each have their own, and because the taxonomy was replaced once and the old one was kept.
The trees
| Tree | Table | From | Role |
|---|---|---|---|
| Akeneo taxonomy | productcategories | app/jobs/akeneo/getcategories.php | The live one. Every product carries a main category from it |
| Akeneo top level | productcategoriestoplevel | config/reference/productcategoriestoplevel.json via the installer | CCC's reporting groups, matched to Akeneo codes by the category import |
| NetSuite categories | ns_categories | app/jobs/netsuite/categories.php | NetSuite's own classification, arriving with the item data |
| Retired taxonomy | productcategories_old, productcategoriestoplevel_old | Seeded once by seed_categories_old.php | Kept so figures produced under the old tree can still be read |
The retired pair is seeded through config/seed/, which means the database owns it after the first install: it is history, and nothing refreshes it.
The top-level category is the one reports use. A product's full path can be several levels deep and is not comparable across brands; the top level is, which is why it is a column on the product rather than something a report derives.
Where it comes from
app/jobs/akeneo/getcategories.php consumes the akeneo_getcategories batch type, writes the translations into productcategorylanguages_new and swaps them in, guarded on row count. app/jobs/netsuite/categories.php consumes ns_categories and replaces ns_categories wholesale on the swap pattern.
A category carries a code, a name, a parentcode that builds the tree, and an akeneocode on the top-level rows that ties the two systems together.
Where to look
/entities/categories carries the trees as tabs:
| Tab | Shows |
|---|---|
| (default) | The Akeneo taxonomy, with each category's top level |
| Old | The retired taxonomy |
| NS | NetSuite's categories, with their full name and parent |
| TLC | The Akeneo top-level categories |
| TLC old | The retired top-level categories |
These are listing views. Change imported categories in Akeneo or NetSuite. Change CCC's top-level mapping in its reference JSON and run the installer, then refresh categories and products and reclassify affected transaction dates. The retained old taxonomy is separate from that mapping.
Related
Evidence
Imports and the guarded swap from app/jobs/akeneo/getcategories.php and app/jobs/netsuite/categories.php. The retired pair from app/jobs/install/seed_categories_old.php and the config/seed/ rule in AGENTS.md, Configuration and .env. Tabs from app/http/entities/categories.php and the tables in templates/main/entities/categories.tpl. Basis: code-checked against the current implementation.
- Type
object - Status
active - Updated
2026-09-14 - Created
2026-09-13 - Covers
entities/categories