Inventory Reporter releases
A read-only WooCommerce inventory & sales report for the WordPress admin — filter by category, stock status, date range and SKU, sort any column, and export to CSV.
by Humanear, Inc. · github.com/humanear/inventory-reporter · website
Install
The author publishes release zips, so WP-CLI can install straight from GitHub:
wp plugin install https://github.com/humanear/inventory-reporter/releases/download/v1.4.1/ss-inventory-reporter-1.4.1.zipPlugin slug: ss-inventory-reporter
Version: 1.4.1
Author: Humanear, Inc.
Requires: WordPress 6.0+, WooCommerce (current stable), PHP 8.0+
What This Plugin Does
Adds an Inventory Report page inside WooCommerce in WP Admin. Store administrators can:
- View all products (simple + variable/variation rows) with current stock levels.
- See units sold and last sale date for any time period.
- Filter by date range, category, stock status, and product name / SKU.
- Export the filtered view to a CSV file.
- Use the data to standardize product weights in the shipping system.
This plugin is read-only — it never modifies stock levels or order data.
Installation
From a release ZIP (recommended):
- Download the latest
ss-inventory-reporter-x.y.z.zipfrom the Releases page. - In WP Admin, go to Plugins → Add New → Upload Plugin, choose the ZIP, and click Install Now.
- Click Activate.
Manual install:
- Upload the
ss-inventory-reporterfolder to/wp-content/plugins/. - In WP Admin → Plugins, activate Inventory Reporter.
Then:
- WooCommerce must be installed and active — otherwise the plugin shows an admin notice and does nothing.
- Open WooCommerce → Inventory Report in the left admin menu.
Access Control
Only users with the manage_woocommerce capability (Administrators and Shop Managers by default) can view the report or export data.
- Direct URL access is blocked — the capability check runs on every page load, independent of the menu.
- The CSV export endpoint has its own independent capability check.
Using the Filters
All filters apply simultaneously (AND logic). Submit the form to apply; click Reset to clear all filters.
Sales Period
Controls the date range for Units Sold and Last Sale Date columns. Stock Qty always reflects the current live value.
| Option | What it covers |
|---|---|
| Last 7 Days | Rolling 7-day window ending today |
| Last 30 Days | Rolling 30-day window (default) |
| Last 90 Days | Rolling 90-day window |
| This Month | 1st of current month → today |
| Last Month | Full previous calendar month |
| This Year | Jan 1 of current year → today |
| Last Year | Full previous calendar year |
| Custom Range | Pick your own From / To dates |
Category
Filter to one or more WooCommerce product categories using the checkbox list. A product matches if it belongs to any of the checked categories. Child categories are included automatically when you check a parent. Leave every box unchecked to include all categories.
Stock Status
| Option | What it shows |
|---|---|
| All | Every product |
| In Stock | stock_status = instock |
| Out of Stock | stock_status = outofstock |
| Low Stock | In stock, qty > 0, qty ≤ WC low-stock threshold |
| On Backorder | stock_status = onbackorder |
The Low Stock threshold is read from WooCommerce → Settings → Products → Inventory → Low stock threshold.
Search
Partial, case-insensitive match against product name and SKU. Searches both simple product names and variation parent names.
Hide products with 0 units sold
Tick the Hide 0 units sold box in the toolbar to drop every product that recorded no sales in the selected period. It's applied after the data is fetched (so toggling it is instant and never re-queries the database), and it also adjusts the summary totals and the CSV export to match what's shown.
Column-level SKU filter
The SKU column header has a Filter SKUs dropdown (a native disclosure panel — no JavaScript). Open it to see a checklist of every SKU in the current result set — i.e. all the SKUs for whatever category/date/stock/search filters are currently applied. Each SKU shows its Units Sold quantity for the selected period in parentheses, e.g. 1156 (12). Tick the SKUs you want and click Apply (inside the panel) to narrow the table to just those.
Typical flow: pick a category (e.g. Roll Tubes) → Apply Filters → open the Filter SKUs dropdown → the list now shows just the roll-tube SKUs → tick the ones you want → Apply.
- The checklist always shows the full set of SKUs for the current filters, regardless of which ones are already selected, so you can freely add or remove.
- The dropdown reopens automatically when a SKU selection is active, and shows a count (e.g. SKUs (3)). A Clear link removes the SKU selection while keeping your other filters.
- The selection is applied in PHP on the cached data (instant, no re-query) and carries through sorting, pagination, and the CSV export.
Dealer price columns
The report shows a Retail column (the product's regular price) plus one column per dealer role — Bronze, Platinum, and Pinnacle Trailers — each sortable and included in the CSV export.
Prices come from the Role Based Pricing for WooCommerce plugin's per-product rules (stored as per-role _role_base_price_{role} meta) and are computed for every adjustment type it supports: fixed price, fixed increase/decrease, and percentage increase/decrease. A product with no dealer rule for a tier simply shows its retail price there.
Only the single-unit base price is shown. Quantity-tier rules (minimum quantity above 1) and date-limited rules that aren't currently in effect are treated as not applicable, so those products show retail for that tier.
The roles and the meta key prefix are configurable for other stores via the ss_inv_role_price_roles and ss_inv_role_price_meta_prefix filters.
Price filter
Use the Price Filter control in the toolbar: pick a tier (Retail or a dealer role) from the dropdown, then set a Min and/or Max — e.g. "Bronze between $50 and $200." Products with no price for the chosen tier are excluded while the filter is active. It runs in PHP on the cached data (instant) and carries through sorting, pagination, and the CSV export.
Sorting
Click any column header to sort the table by that column. An arrow appears on the active column (▲ ascending, ▼ descending); click the same header again to flip the direction. Sorting applies across the entire result set, not just the visible page, and resets you to page 1.
- Stock Qty and Units Sold sort numerically; Last Sale Date sorts chronologically; all other columns sort alphabetically (case-insensitive).
- Rows with no value for the sorted column (e.g. unmanaged stock, or no recorded sale) always sink to the bottom, in both directions.
- Sorting runs in PHP on the cached data, so it's instant and never re-queries the database. The CSV export reflects whatever sort is currently applied.
CSV Export
Click Export to CSV in the filter toolbar. The export downloads all rows matching the current filters — not just the current page.
- Filename:
YYYY.MM.DD-{site-name}-inventory-report.csv— e.g.2026.06.24-sioux-city-tarp-inventory-report.csv(the site-name portion is derived automatically from your WordPress Site Title). - UTF-8 encoded with BOM (opens correctly in Excel without manual import steps).
- Column order: Product Name, SKU, Type, Category, Retail, Bronze, Platinum, Pinnacle Trailers, Stock Status, Stock Qty, Units Sold (period), Last Sale Date.
- CSV injection safe — a value beginning with a formula trigger (
=,+,-,@, tab, or carriage return) is prefixed with a single quote, neutralizing it while preserving the value.
Refresh Data
Results are cached for 15 minutes to improve performance. Click Refresh Data to bust the cache and fetch fresh data from the database immediately.
Table Columns
| Column | Description |
|---|---|
| Product Name | Base product name. For variations, shows the parent product name. |
| SKU | Product or variation SKU. |
| Type | "Simple" for simple products. "Variable / Size: XL, Color: Black" for variations. |
| Category | WooCommerce product categories (comma-separated). |
| Stock Status | In Stock / Out of Stock / On Backorder (colour-coded badges). |
| Stock Qty | Current numeric stock. Shows — if stock management is disabled for the product. |
| Units Sold | Total quantity sold across completed + processing orders in the selected period. |
| Last Sale Date | Date of the most recent qualifying order containing this product/variation. |
Summary Bar
The row of metric cards above the table shows:
- Total SKUs — count of rows in the current filtered view.
- Units In Stock — sum of Stock Qty across all matching rows (managed products only).
- Units Sold — sum of Units Sold for the selected period.
- Out of Stock — count of rows where Stock Status = Out of Stock.
All four metrics recalculate when you apply different filters.
Performance Notes
- Results are cached in WP transients for 15 minutes per filter combination.
- The table displays 50 rows per page.
- All queries use
$wpdb->prepare()prepared statements. - The sales query joins
woocommerce_order_itemsandwoocommerce_order_itemmeta— this works with WooCommerce's legacy order storage. Sites that have migrated to WooCommerce HPOS (High Performance Order Storage) will need a query update to use thewc_orderstable.
Order Statuses Counted as "Sold"
Only orders with these WooCommerce statuses count toward Units Sold:
wc-completedwc-processing
The following are excluded: pending, on-hold, cancelled, refunded, failed.
Security
This plugin follows all WordPress coding standards and security best practices:
- Access control —
manage_woocommercecapability checked on every request. - CSRF protection — WordPress nonces on all form submissions and the CSV export.
- SQL injection prevention —
$wpdb->prepare()with typed placeholders on all queries. - XSS prevention —
esc_html(),esc_attr(),esc_url()at every output point. - CSV injection prevention — any cell value beginning with a formula trigger (
=,+,-,@, tab, or carriage return) is prefixed with a single quote, neutralizing it in spreadsheet apps while preserving the original value. - Input sanitization — every filter input is sanitized and/or whitelist-validated before use.
Troubleshooting
"No products found matching your filters" — Your filter combination returned no results. Try widening the date range or clearing other filters.
"Unable to load inventory data" — A database query failed. Check WP debug log (wp-content/debug.log) for details. This is usually a temporary database connectivity issue.
Inventory Report not visible in menu — Your user account does not have the manage_woocommerce capability. Log in as an Administrator.
Units Sold shows 0 for everything — Check that your orders have wc-completed or wc-processing status, and that the date range covers the period when orders were placed.
File Structure
ss-inventory-reporter/
├── ss-inventory-reporter.php # Main plugin file — bootstrap, menu, filters, CSV hook
├── includes/
│ ├── class-inventory-query.php # All $wpdb queries — products, sales, categories
│ ├── class-inventory-table.php # HTML rendering — filter toolbar, summary bar, table, pagination
│ └── class-csv-export.php # CSV streaming with CSV injection protection
├── assets/
│ ├── admin.css # Admin page styling
│ └── admin.js # Custom date range toggle (vanilla JS)
├── README.md # This file
├── CHANGELOG.md # Version history
├── LICENSE # GPL-2.0 license text
└── .gitignore # Files Git should ignore
Contributing
Issues and pull requests are welcome. This is a self-contained plugin with no
build step — edit the PHP/CSS/JS directly. Please keep the existing code style
(heavily commented, WordPress coding standards, vanilla JS) and update
CHANGELOG.md with any user-facing change.
To package a release ZIP from the plugin folder:
zip -r ss-inventory-reporter-x.y.z.zip ss-inventory-reporter -x "*.DS_Store"
License
Released under the GNU General Public License v2.0 or later (GPL-2.0+), consistent with WordPress and WooCommerce. See the LICENSE file for the full text.
Built by Humanear, Inc. — humanear.com
Releases
3 releases. Each count is every asset in that release; expand a row for the breakdown.