# Contract: Import / Export Workflows ## Import Workflow Recommended stages: 1. `Upload` 2. `Preview / Validate` 3. `Confirm` 4. `Execute` 5. `Result summary` Rules: - Validation preview must be human-readable (table/list), not raw JSON only. - Warnings and errors should be shown per row and in aggregate summary. - Confirm step should clearly communicate scope and side effects. ## Export Workflow - User must explicitly choose export scope (`selected`, `filtered`, `all`) when ambiguity exists. - Export format should be explicit (`csv`, `json`, etc.). - Download response must set: - `Content-Type: text/csv; charset=utf-8` - `Content-Disposition: attachment; filename="..."` ## CSV Format Rules (Excel-compatible) These rules are **mandatory** whenever CSV is exported for spreadsheet users. ### Encoding and BOM - Write UTF-8 BOM (`\xEF\xBB\xBF`) as the very first bytes of the response. - Without BOM, Excel on Windows opens UTF-8 CSV as ANSI and garbles Cyrillic/special characters. ```go w.Write([]byte{0xEF, 0xBB, 0xBF}) ``` ### Delimiter - Use **semicolon** (`;`) as the field delimiter, not comma. - Excel in Russian/European locale uses semicolon as the list separator. - Comma-delimited files open as a single column in these locales. ### Numbers - Write decimal numbers with a **comma** as the decimal separator: `1 234,56` — not `1234.56`. - Excel in Russian locale does not recognize period as a decimal separator in numeric cells. - Format integers and floats explicitly; do not rely on Go's default `%v` or `strconv.FormatFloat`. - Use a thin non-breaking space (`\u202F`) or regular space as a thousands separator when the value benefits from readability (e.g. prices, quantities > 9999). ```go // correct fmt.Sprintf("%.2f", price) // then replace "." -> "," strings.ReplaceAll(fmt.Sprintf("%.2f", price), ".", ",") // wrong — produces "1234.56", Excel treats it as text in RU locale fmt.Sprintf("%.2f", price) ``` ### Dates - Write dates as `DD.MM.YYYY` — the format Excel in Russian locale parses as a date cell automatically. - Do not use ISO 8601 (`2006-01-02`) for user-facing CSV; it is not auto-recognized as a date in RU locale. ### Text quoting - Wrap any field that contains the delimiter (`;`), a newline, or a double-quote in double quotes. - Escape embedded double-quotes by doubling them: `""`. - Use `encoding/csv` with `csv.Writer` and set `csv.Writer.Comma = ';'`; it handles quoting automatically. ## Error Handling - Import errors should map to clear user-facing messages. - Export errors after streaming starts must degrade gracefully (human-readable fallback).