All files / src/api/analytics validation.ts

100% Statements 78/78
100% Branches 3/3
100% Functions 3/3
100% Lines 78/78

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 791x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x 1x  
/**
 * @file validation.ts
 * @module api/analytics/validation
 *
 * @summary
 * Centralized validation schemas for analytics query parameters.
 * Zod schemas for common analytics filters and date ranges.
 *
 * @enterprise
 * - All analytics queries validate parameters before API calls
 * - Consistent date format handling (ISO 8601)
 * - Optional supplier filtering with validation
 * - Type-safe parameter validation
 */
 
import { z } from 'zod';
 
/**
 * Base parameters for analytics queries with optional date range and supplier filter.
 * Used by most analytics endpoints for consistent parameter handling.
 * Dates are optional but recommended for trend queries.
 */
export const analyticsParamsSchema = z.object({
  from: z.string().date().optional(),           // ISO date YYYY-MM-DD
  to: z.string().date().optional(),             // ISO date YYYY-MM-DD
  supplierId: z.string().optional(),             // Optional supplier filter
});
 
export type AnalyticsParams = z.infer<typeof analyticsParamsSchema>;
 
/**
 * Parameters specifically for price trend queries.
 * Requires itemId, dates are required for meaningful trends.
 * Optional supplier filter.
 */
export const priceTrendParamsSchema = z.object({
  itemId: z.string().min(1, 'Item ID is required'),
  start: z.string().date('Start must be a valid date (YYYY-MM-DD)'),
  end: z.string().date('End must be a valid date (YYYY-MM-DD)'),
  supplierId: z.string().optional(),
}).refine(
  (data) => data.start <= data.end,
  { message: 'Start date must be before or equal to end date', path: ['start'] }
);
 
export type PriceTrendParams = z.infer<typeof priceTrendParamsSchema>;
 
/**
 * Parameters for stock movement queries.
 * Requires date range for meaningful movement analysis.
 * Optional supplier filter.
 */
export const stockMovementParamsSchema = z.object({
  start: z.string().date('Start must be a valid date (YYYY-MM-DD)'),
  end: z.string().date('End must be a valid date (YYYY-MM-DD)'),
  supplierId: z.string().optional(),
}).refine(
  (data) => data.start <= data.end,
  { message: 'Start date must be before or equal to end date', path: ['start'] }
);
 
export type StockMovementParams = z.infer<typeof stockMovementParamsSchema>;
 
/**
 * Parameters for financial summary queries.
 * Requires date range for WAC calculations.
 * Optional supplier filter
 */
export const financialSummaryParamsSchema = z.object({
  from: z.string().date('From date must be a valid date (YYYY-MM-DD)'),
  to: z.string().date('To date must be a valid date (YYYY-MM-DD)'),
  supplierId: z.string().optional(),
}).refine(
  (data) => data.from <= data.to,
  { message: 'From date must be before or equal to to date', path: ['from'] }
);
 
export type FinancialSummaryParams = z.infer<typeof financialSummaryParamsSchema>;