Home / Help Center / pos-app-garment / garment / Age of Inventory
📦 garment

Age of Inventory

Age of Inventory lists every in-stock product with a "days old" figure and buckets the whole catalog into 0-30, 31-90, 91-180 and 180+ day age bands, so you can spot dead stock at a glance before deciding what to send to Markdown Rules or clearance.

📍 Menu path: /garment/age-of-inventory
👤 Who uses it: Owner,Manager

Overview

The page loads up to 1,000 products from the generic product catalog and keeps only active products (isActive !== false) that currently have stock greater than zero — items with no stock left have nothing to mark down, so they are excluded entirely.

Age ("days old") is computed client-side from each product's createdAt timestamp, using the exact same definition as the Markdown Rules preview calculation on the backend — so the "days old" you see here should always agree with what a matching Markdown Rule preview would report for the same product.

Four clickable bucket tiles (0–30 days, 31–90 days, 91–180 days, 180+ days) show a live count for each age band; clicking one filters the table down to just that band, click again to clear it.

A running "Estimated dead-stock cost value" figure (cost price × stock quantity, summed) is shown above the table and recalculates against whatever the current search/season/bucket filters have narrowed the list down to.

Before You Start

Step-by-Step Guide

1 Spot dead stock via the age buckets

  1. Look at the four bucket tiles at the top — 0–30 days (green), 31–90 days (amber), 91–180 days (orange) and 180+ days (red) — each shows a live count of in-stock products in that age range.
  2. Click a tile to filter the table to just that band; click the same tile again to clear the filter.
  3. Treat the 180+ days tile as your priority clearance list — those items have been sitting the longest.

2 Search, filter and sort the list

  1. Use the search box to filter by product name or SKU.
  2. Use the Season dropdown (if shown) to narrow to a single season, e.g. "SS25".
  3. Use the sort dropdown — Oldest first, Newest first, Most stock, or Name A-Z.
  4. Click Clear filters to reset search, season and bucket selections at once.

3 Use the age figures to decide on a markdown

  1. Note the SKUs sitting in the 91–180 or 180+ day buckets with meaningful stock quantity and cost value.
  2. Go to Markdown Rules and create or run a rule scoped to the same Season/Category to discount them, using Preview first to confirm the same products show up.

Every Field & Button, Explained

Field / ButtonWhat it does
Age bucket tiles0-30 days, 31-90 days, 91-180 days, 180+ days — each clickable to filter the table to that band; counts are computed across every in-stock product regardless of other active filters.
Search boxFilters by product name or SKU (case-insensitive substring match).
Season dropdownFilters to a single Season value; only rendered when at least one in-stock product has a Season set.
Sort dropdownOldest first, Newest first, Most stock, or Name A-Z.
Clear filtersResets search, season and bucket selection together; only shown once at least one filter is active.
Estimated dead-stock cost valueSum of cost price × stock quantity across the currently filtered/sorted list of products (not the whole catalog) — changes as you apply search/season/bucket filters.
Table — Product / SKU / Brand / SeasonBasic identifying columns; Season is shown as a badge, "—" if not set.
Table — StockCurrent stock quantity on hand.
Table — Cost/unit, ValueCost price per unit, and Cost/unit × Stock as that row's contribution to the dead-stock value figure.
Table — AgeDays since the product record was created, colour-coded to match its age bucket.

Tips & Best Practices

Troubleshooting & FAQ

A product I know is old shows a low "days old" number.
Age is computed from the product record's creation date (createdAt) in the system, not from when it was last restocked or put on the floor — if the SKU's record was edited/recreated recently, or if only the stock quantity was topped up, the age will look newer than the physical garment actually is.
A product I know is sitting unsold is missing from the list entirely.
The page only shows products with stock quantity greater than zero and marked active — if it has sold completely out, or been deactivated, it will not appear here even though it may still show up in other product lists.
There is no Season dropdown on my screen.
It only renders when at least one in-stock product currently has a Season value set — if none of your products use the Season field yet, the dropdown is hidden rather than shown empty.
The dead-stock value total changed after I searched or filtered.
The total is calculated from whatever the current filtered/sorted table shows, not the full unfiltered catalog — clear filters to see the value across everything in stock.

🧑‍💻 Developer Notes

Source component(s):

  • frontend-app/pos-app-garment/src/pages/garment/AgeOfInventoryPage.jsx

Backend endpoints used:

  • GET /products (limit=1000) — the generic product-listing endpoint; there is no dedicated garment route for this page

Related tables (db-core repositories):

  • Product

Redux slices:

  • None — local component state only

Feature flag key: inventory

No dedicated garment.routes.js endpoint backs this page — it simply calls the generic GET /products endpoint with a high limit and computes buckets, sorting, filtering and the dead-stock value figure entirely client-side (see daysOld() and getBucket() at the top of AgeOfInventoryPage.jsx). The daysOld() calculation is textually identical in spirit to the one in packages/pos-core/src/garment.js's previewMarkdownRule, so the two pages should always agree on a given product's age. This client-only implementation also means large catalogs (beyond the 1000-row limit param) will silently truncate rather than paginate.