Skip to content

feat(csv): add column mapping for CSV imports#28

Merged
Jench2103 merged 10 commits intomainfrom
feat/csv-column-mapping
Mar 24, 2026
Merged

feat(csv): add column mapping for CSV imports#28
Jench2103 merged 10 commits intomainfrom
feat/csv-column-mapping

Conversation

@Jench2103
Copy link
Owner

@Jench2103 Jench2103 commented Mar 24, 2026

Summary

Add a column mapping feature to both ImportView and BulkEntryView that allows users to import CSV files with non-standard column headers without manual renaming. When CSV headers don't match the expected column names, a mapping sheet appears automatically; when they match (case-insensitive), parsing proceeds directly with no extra steps.

Column Mapping Sheet

Changes

  • Column mapping types and auto-detection (CSVParsingTypes.swift, CSVParsingService+ColumnMapping.swift)

    • Add CanonicalColumn, CSVColumnSchema, CSVColumnMapping, and CSVAutoDetectResult types
    • Add extractHeaders, extractSampleRows, autoDetectMapping, and mapping-based parseAssetCSV/parseCashFlowCSV overloads
    • Guard required columns in mapping-based parse methods to prevent silent wrong-column fallback
  • ColumnMappingSheet (Views/Components/ColumnMappingSheet.swift)

    • Shared SwiftUI sheet with full CSV table preview and per-column dropdowns
    • Auto-detected matches are preselected; validation disables Confirm until all required columns are mapped
    • Uses NavigationStack with toolbar for macOS Liquid Glass integration
    • Localized for English and Traditional Chinese (zh-Hant)
  • ImportView integration (ImportViewModel.swift, ImportView.swift)

    • loadCSVData now auto-detects headers and shows mapping sheet when needed
    • confirmColumnMapping parses with the user's mapping and feeds into the existing preview pipeline
    • Empty/invalid files bypass mapping and fall through to existing error reporting
  • BulkEntryView integration (BulkEntryViewModel.swift, BulkEntryView.swift)

    • Add loadCSVForMapping and confirmColumnMapping methods
    • Platform column excluded from mapping options (platform already determined by import section)
    • Refactored importCSV to delegate to importCSVFromParsedRows, eliminating duplicated logic
  • Documentation

    • Updated SPEC.md, APIDesign.md, BusinessLogic.md, UserInterfaceDesign.md
    • Added Column Mapping section to user guide (English and zh-TW) with screenshot

Testing

  • 13 new tests in CSVColumnMappingTests covering extractHeaders, extractSampleRows, autoDetectMapping, mapping-based parsing, and round-trip consistency
  • 8 new tests in ImportViewModelTests covering auto-detect skip, mapping sheet trigger, confirmColumnMapping, partial mapping, cash flow variant, and state cleanup
  • 3 new tests in BulkEntryViewModelTests covering canonical pass-through, non-matching sheet trigger, and confirmColumnMapping result
  • All existing tests pass (full suite green)

🤖 Generated with Claude Code

Jench2103 and others added 10 commits March 24, 2026 09:55
Add CanonicalColumn, CSVColumnSchema, CSVColumnMapping, and
CSVAutoDetectResult types for mapping arbitrary CSV headers to
AssetFlow's expected columns.

Add extractHeaders, extractSampleRows, autoDetectMapping, and
mapping-based parseAssetCSV/parseCashFlowCSV overloads to
CSVParsingService. These enable CSV import without requiring
users to manually rename columns.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Shared sheet component for mapping arbitrary CSV column headers to
AssetFlow's canonical columns (Asset Name, Market Value, etc.).

Displays a full CSV table preview with per-column dropdowns,
auto-detects and pre-selects matching columns, validates that all
required columns are mapped without duplicates.

Uses NavigationStack with toolbar for macOS Liquid Glass integration.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
loadCSVData now auto-detects column headers. If they match the
expected canonical columns (case-insensitive), parsing proceeds
immediately. If not, the mapping sheet state is populated so the
view can present ColumnMappingSheet for user-driven mapping.

confirmColumnMapping accepts the user's mapping and parses the
CSV using the mapping-based overloads. clearLoadedData resets
all mapping state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add loadCSVForMapping to BulkEntryViewModel that auto-detects CSV
headers. If they match, importCSV runs directly. Otherwise, mapping
state is populated for ColumnMappingSheet presentation.

confirmColumnMapping accepts the user's mapping and imports the
parsed rows into the bulk entry table.

BulkEntryView now shows ColumnMappingSheet when needed and displays
import results after mapping confirmation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Update SPEC.md to replace deferred column mapping note with full
description and remove from future features list.

Update APIDesign.md with new CSVParsingService methods and column
mapping types.

Update BusinessLogic.md import flow with auto-detection step.

Update UserInterfaceDesign.md with column mapping sheet description.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace force unwrap with optional map and use for-where clause.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…g sheet

Add instructional hint text above the CSV table preview. Add padding
between CSV content and horizontal scroll bar. Use horizontal-only
scroll so the sheet height fits its content dynamically.

Add Traditional Chinese (zh-Hant) translations for all column
mapping strings in the Import string catalog.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
BulkEntryView imports CSV per-platform, so the platform is already
known. Add assetWithoutPlatform schema variant that omits Platform
from the mapping options to avoid confusion.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add Column Mapping section to import-csv guide explaining auto-
detection, the mapping sheet UI, preselection, validation, and
re-mapping. Add tip callout to the file requirements table pointing
users to the new section.

Add column mapping paragraph to bulk-entry per-platform CSV import
section, noting that Platform is excluded from the mapping options.

Both English and Traditional Chinese (zh-TW) versions updated.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
1. Guard required columns in mapping-based parse methods — return
   error result instead of silently defaulting to wrong indices.
2. Set selectedFileData at the start of loadCSVData to prevent nil
   when called directly without loadFile.
3. Refactor importCSV to delegate to importCSVFromParsedRows,
   eliminating ~60 lines of duplicated matching logic.
4. Add comment explaining intentional triple-decode trade-off
   (clarity over micro-optimization for small data).
5. Compute duplicateColumns once per render in csvTable, not per
   pickerCell call.
6. Fix unused variable warning in BulkEntryViewModelTests.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@Jench2103 Jench2103 self-assigned this Mar 24, 2026
@Jench2103 Jench2103 added enhancement New feature or request ui / ux i18n Internationalization and localization documentation Improvements or additions to documentation labels Mar 24, 2026
@Jench2103 Jench2103 merged commit 6b04e1c into main Mar 24, 2026
1 check passed
@Jench2103 Jench2103 deleted the feat/csv-column-mapping branch March 24, 2026 06:11
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

documentation Improvements or additions to documentation enhancement New feature or request i18n Internationalization and localization ui / ux

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant