calculate_inventory_value
Calculate total inventory value with filtering by status, category, location, or price range. Get item count, average value, and breakdowns by category, location, or account for consignment business analysis.
Instructions
Calculate total inventory value with comprehensive filtering and grouping. Returns total value, item count, average value, and optional breakdown by category, location, account, inventory type, or status.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| status | No | Filter by status (available, sold, processing, removed) | |
| category | No | Filter by category ID | |
| account | No | Filter by account ID | |
| location | No | Filter by location ID | |
| inventory_type | No | Filter by inventory type | |
| tag_price_gte | No | Filter items with price >= this value (in cents) | |
| tag_price_lte | No | Filter items with price <= this value (in cents) | |
| date_from | No | Filter items created on or after this date (ISO 8601: YYYY-MM-DD) | |
| date_to | No | Filter items created on or before this date (ISO 8601: YYYY-MM-DD) | |
| batch | No | Filter by batch ID | |
| group_by | No | Group results by field for detailed breakdown |
Implementation Reference
- src/client.ts:444-575 (handler)Main handler function that implements the tool logic: paginates through all matching inventory items using API filters, applies client-side date filtering, computes total value as sum of (tag_price * quantity) for available items, supports optional grouping by category/location/account/type/status, and returns formatted results with applied filters summary.async calculateInventoryValue(params?: { status?: string; category?: string; account?: string; location?: string; inventory_type?: string; tag_price_gte?: number; tag_price_lte?: number; date_from?: string; date_to?: string; batch?: string; group_by?: 'category' | 'location' | 'account' | 'inventory_type' | 'status'; }): Promise<InventoryValueResult> { const { group_by, ...filterParams } = params || {}; const filters: string[] = []; // Track applied filters if (filterParams.status) filters.push(`status=${filterParams.status}`); if (filterParams.category) filters.push(`category=${filterParams.category}`); if (filterParams.account) filters.push(`account=${filterParams.account}`); if (filterParams.location) filters.push(`location=${filterParams.location}`); if (filterParams.inventory_type) filters.push(`inventory_type=${filterParams.inventory_type}`); if (filterParams.tag_price_gte) filters.push(`tag_price>=${filterParams.tag_price_gte}`); if (filterParams.tag_price_lte) filters.push(`tag_price<=${filterParams.tag_price_lte}`); if (filterParams.date_from) filters.push(`date_from=${filterParams.date_from}`); if (filterParams.date_to) filters.push(`date_to=${filterParams.date_to}`); if (filterParams.batch) filters.push(`batch=${filterParams.batch}`); let allItems: Item[] = []; let cursor: string | null = null; // Build query params with only defined values (excluding date filters - not supported by API) const queryParams: Record<string, any> = { limit: 100 }; if (filterParams.status) queryParams.status = filterParams.status; if (filterParams.category) queryParams.category = filterParams.category; if (filterParams.account) queryParams.account = filterParams.account; if (filterParams.location) queryParams.location = filterParams.location; if (filterParams.inventory_type) queryParams.inventory_type = filterParams.inventory_type; if (filterParams.tag_price_gte !== undefined) queryParams.tag_price_gte = filterParams.tag_price_gte; if (filterParams.tag_price_lte !== undefined) queryParams.tag_price_lte = filterParams.tag_price_lte; if (filterParams.batch) queryParams.batch = filterParams.batch; // NOTE: date_from/date_to NOT sent to API (not supported) - will filter client-side // Fetch all pages do { if (cursor) queryParams.cursor = cursor; const response = await this.listItems(queryParams); allItems = allItems.concat(response.data); cursor = response.next_cursor; } while (cursor); // Apply client-side date filtering (API doesn't support this) if (filterParams.date_from || filterParams.date_to) { allItems = allItems.filter(item => { if (!item.created) return false; const itemDate = new Date(item.created); if (filterParams.date_from && itemDate < new Date(filterParams.date_from)) return false; if (filterParams.date_to && itemDate > new Date(filterParams.date_to)) return false; return true; }); } // Calculate totals let totalValue = 0; let totalItems = 0; const breakdown: Record<string, { value: number; value_formatted: string; count: number }> = {}; for (const item of allItems) { // Items don't have a simple quantity field - use 1 as default or count from status const quantity = item.quantity || 1; const itemValue = item.tag_price * quantity; totalValue += itemValue; totalItems += quantity; // Group by if specified if (group_by) { let groupKey: string; switch (group_by) { case 'category': groupKey = item.category || 'uncategorized'; break; case 'location': groupKey = item.location || 'no_location'; break; case 'account': groupKey = item.account || 'no_account'; break; case 'inventory_type': groupKey = item.inventory_type; break; case 'status': groupKey = item.status; break; default: groupKey = 'all'; } if (!breakdown[groupKey]) { breakdown[groupKey] = { value: 0, value_formatted: '', count: 0 }; } breakdown[groupKey].value += itemValue; breakdown[groupKey].count += quantity; } } // Format breakdown values const formattedBreakdown: Record<string, { value: number; value_formatted: string; count: number }> | undefined = group_by ? Object.fromEntries( Object.entries(breakdown).map(([key, data]) => [ key, { value: data.value, value_formatted: this.formatAmount(data.value), count: data.count } ]) ) : undefined; const avgValue = totalItems > 0 ? Math.round(totalValue / totalItems) : 0; return { total_value: totalValue, total_value_formatted: this.formatAmount(totalValue), total_items: totalItems, average_value: avgValue, average_value_formatted: this.formatAmount(avgValue), breakdown: formattedBreakdown, filters_applied: filters, currency: this.currency, locale: this.locale, }; }
- src/server.ts:326-353 (registration)Tool registration in createTools() array: defines name, detailed description, and input schema matching the client method params for MCP tool listing.{ name: 'calculate_inventory_value', description: 'Calculate total inventory value with comprehensive filtering and grouping. Returns total value, item count, average value, and optional breakdown by category, location, account, inventory type, or status.', inputSchema: { type: 'object', properties: { status: { type: 'string', description: 'Filter by status (available, sold, processing, removed)' }, category: { type: 'string', description: 'Filter by category ID' }, account: { type: 'string', description: 'Filter by account ID' }, location: { type: 'string', description: 'Filter by location ID' }, inventory_type: { type: 'string', enum: ['consignment', 'buy_outright', 'retail'], description: 'Filter by inventory type' }, tag_price_gte: { type: 'number', description: 'Filter items with price >= this value (in cents)' }, tag_price_lte: { type: 'number', description: 'Filter items with price <= this value (in cents)' }, date_from: { type: 'string', description: 'Filter items created on or after this date (ISO 8601: YYYY-MM-DD)' }, date_to: { type: 'string', description: 'Filter items created on or before this date (ISO 8601: YYYY-MM-DD)' }, batch: { type: 'string', description: 'Filter by batch ID' }, group_by: { type: 'string', enum: ['category', 'location', 'account', 'inventory_type', 'status'], description: 'Group results by field for detailed breakdown' }, }, }, },
- src/server.ts:509-510 (handler)MCP server dispatch handler: receives tool call params and delegates execution to client.calculateInventoryValue, serializes result as JSON text response.case 'calculate_inventory_value': return { content: [{ type: 'text', text: JSON.stringify(await client.calculateInventoryValue(args as any), null, 2) }] };
- src/types.ts:89-105 (schema)TypeScript interface defining the output structure of the calculateInventoryValue method, used for type safety in the client implementation.export interface InventoryValueResult { total_value: number; // in cents total_value_formatted: string; // locale-formatted (e.g., "1,234.56" or "1.234") total_items: number; average_value: number; // in cents average_value_formatted: string; // locale-formatted breakdown?: { [key: string]: { value: number; value_formatted: string; count: number; }; }; filters_applied: string[]; currency: string; // ISO currency code (e.g., "ISK", "USD") locale: string; // BCP 47 locale (e.g., "is-IS", "en-US") }