Admin can filter orders by status, date range, or total amount
Why it matters
Search by identifier (handled by order-search) and structured filtering are complementary and both required. An admin who can find a specific order by ID but cannot filter to 'all pending orders from the last 7 days' cannot manage their queue proactively — they can only react to inbound support contacts. iso-25010:2011 operability requires that the system supports the work patterns of its operators. For order operations, that means at minimum: filter by status (to work a specific queue) and filter by date range (to find orders placed in a given period). Without server-side filtering, a client-side filter on a paginated list gives false confidence while silently excluding records off the first page.
Severity rationale
Low because the absence of structured filters degrades admin efficiency but does not prevent order processing — admins can still use search and pagination to manage orders manually.
Remediation
Add status, from, to, minTotal, and maxTotal filter parameters to the admin orders API at app/api/admin/orders/route.ts and apply them server-side.
// app/api/admin/orders/route.ts
const { searchParams } = new URL(req.url)
const status = searchParams.get('status')
const from = searchParams.get('from')
const to = searchParams.get('to')
const minTotal = searchParams.get('minTotal')
const maxTotal = searchParams.get('maxTotal')
const where: Prisma.OrderWhereInput = {}
if (status) where.status = status
if (from || to) where.createdAt = {
...(from ? { gte: new Date(from) } : {}),
...(to ? { lte: new Date(to) } : {}),
}
if (minTotal || maxTotal) where.total = {
...(minTotal ? { gte: parseInt(minTotal) } : {}),
...(maxTotal ? { lte: parseInt(maxTotal) } : {}),
}
Render a status dropdown and a date range picker in the admin orders UI, both wired to query parameters.
Detection
-
ID:
order-filtering -
Severity:
low -
What to look for: Check the admin orders list for filter controls beyond search. Count the number of distinct filter types available — enumerate each one found: status filter (dropdown or checkbox group), date range picker, total amount range filter, or others. At least 2 filter types are required. Examine the backing API endpoint or query to verify that the filter parameters are actually applied to the database query — not just used for client-side filtering. Quote the exact query parameter names used (e.g.,
?status=,?from=,?to=). -
Pass criteria: The admin orders list includes at least 2 of these 3 filter types: status filter, date range filter, or total amount filter. The filters are applied server-side to the database query, not client-side on a pre-loaded list. Selected filters produce a meaningfully narrowed results set. A single filter type alone (e.g., only status) does not count as pass — at least 2 are required.
-
Fail criteria: The admin order list has fewer than 2 filtering controls — only a full unfiltered list (with optional search). Admins cannot narrow the list to, for example, only
pendingorders from the past week. -
Skip (N/A) when: The project has no admin section. No admin orders list page exists in the codebase.
-
Detail on fail:
"The admin orders list at /admin/orders has 0 filter controls. It displays all orders in reverse chronological order with no way to filter by status, date, or amount. For stores with more than a few dozen orders this becomes unusable." -
Cross-reference: The
order-searchcheck evaluates search by identifier; this check evaluates structured filtering. Both are needed for a functional admin experience — one without the other leaves gaps. -
Remediation: Add filter parameters to your admin orders API (
app/api/admin/orders/route.ts) and filter controls to the UI:// app/api/admin/orders/route.ts export async function GET(req: Request) { const { searchParams } = new URL(req.url) const status = searchParams.get('status') const from = searchParams.get('from') const to = searchParams.get('to') const minTotal = searchParams.get('minTotal') const maxTotal = searchParams.get('maxTotal') const where: Prisma.OrderWhereInput = {} if (status) where.status = status if (from || to) { where.createdAt = { ...(from ? { gte: new Date(from) } : {}), ...(to ? { lte: new Date(to) } : {}), } } if (minTotal || maxTotal) { where.total = { ...(minTotal ? { gte: parseInt(minTotal) } : {}), ...(maxTotal ? { lte: parseInt(maxTotal) } : {}), } } const orders = await db.orders.findMany({ where, orderBy: { createdAt: 'desc' }, take: 100 }) return Response.json({ orders }) }
External references
- iso-25010:2011 · operability — Operability — admin usability
Taxons
History
- 2026-04-18·v1.0.0·Initial import from ecommerce-order-management·automated