# Task D.7.4 CSV Preview Validation Engine

Date: 2026-07-02
Status: implemented

## Scope Delivered

- Added reusable preview-only CSV engine:
  - `src/features/setup/server/csv-preview.service.ts`
  - `src/features/setup/server/csv/parser.ts`
  - `src/features/setup/server/csv/template-registry.ts`
  - `src/features/setup/server/csv/header-validator.ts`
  - `src/features/setup/server/csv/value-validator.ts`
  - `src/features/setup/server/csv/dependency-resolver.ts`
  - `src/features/setup/server/csv/validator.ts`
  - `src/features/setup/server/csv/preview-builder.ts`
  - `src/features/setup/server/csv/types.ts`
- Added protected preview route:
  - `POST /api/setup/import/preview`

## Behavior

- Accepts one or more CSV files through `multipart/form-data`.
- Detects templates by filename from `setup/templates/templates.json`.
- Treats `templates.json` plus checked-in CSV headers as runtime template truth.
- Rejects unknown and unsupported templates with structured row/file errors.
- Validates exact header names, order, duplicate columns, missing columns, and extra columns.
- Parses UTF-8 comma-delimited CSV with quoted cell support.
- Reports invalid encoding, empty rows, duplicate rows, inconsistent column counts, required fields, emails, booleans, integers, decimals, dates, enums, JSON metadata, format rules, and amount/line-total warnings.
- Resolves dependencies from both uploaded batch files and existing database rows without writing.
- Detects duplicate business keys inside each uploaded file.
- Classifies rows as `create`, `update`, or `error`.
- Returns structured file/row report with `PASS`, `WARNING`, `FAIL` status and `previewHash` for D.7.5.

## Safety Notes

- No database insert/update/delete logic added.
- No seed execution added.
- No reset/reseed behavior added.
- No document number generation, approval triggering, PDF generation, or storage writes added.
- Relationship checks use read-only Drizzle selects.
- `quotation-topic-items.csv` resolves `topic_key` from the uploaded batch because `topic_key` is an import-only alias and is not persisted in `crm_quotation_topics`.

## Verification

- `npm run typecheck`: passed.
- `npx oxlint src/features/setup/server/csv src/features/setup/server/csv-preview.service.ts src/app/api/setup/import/preview`: passed.
