CSV and Revolut Imports
Relevant source files
The following files were used as context for generating this wiki page:
- REVOLUT_INTEGRATION.md
- frontend/lib/actions/csv-import.ts
- backend/app/integrations/revolut_csv.py
- frontend/components/transactions/csv-mapping-table.tsx
- frontend/app/(dashboard)/transactions/import/mapping/page.tsx/transactions/import/mapping/page.tsx)
- frontend/scripts/import-revolut-csv.ts
- BANK_INTEGRATION_GUIDE.md
Introduction
The CSV and Revolut Import system provides a robust mechanism for users to programmatically ingest financial data into the application when direct API integrations are unavailable or impractical. This system follows an adapter pattern, allowing the application to handle various file formats and bank-specific exports through a unified interface. Sources: BANK_INTEGRATION_GUIDE.md:6-11, REVOLUT_INTEGRATION.md:5-9
The primary scope of this module includes file uploading, AI-assisted column mapping, transaction previewing with duplicate detection, and final database persistence. While specifically optimized for Revolut exports, the architecture supports generic CSV files through a flexible mapping engine that identifies dates, amounts, and descriptions. Sources: frontend/lib/actions/csv-import.ts:50-95, backend/app/integrations/revolut_csv.py:10-25
Architecture and Data Flow
The import process is divided into a multi-step pipeline managed by Next.js Server Actions on the frontend and Python-based adapters on the backend.
The Import Pipeline
The flow starts with initializing an import session, followed by header parsing, column mapping (optionally AI-assisted), and transaction previewing.
The diagram shows the sequential stages of the CSV import lifecycle from initial upload to database persistence. Sources: frontend/lib/actions/csv-import.ts:50-320, frontend/app/(dashboard)/transactions/import/mapping/page.tsx:75-120
Key Components
| Component | Description | Source |
|---|---|---|
initializeCsvImport | Saves file to storage and creates a session entry in the csvImports table. | csv-import.ts:50-95 |
getAiColumnMapping | Uses gpt-4o-mini to suggest mappings between CSV headers and transaction fields. | csv-import.ts:153-239 |
previewImportedTransactions | Parses the file using the saved mapping and performs duplicate detection. | csv-import.ts:275-400 |
RevolutCSVAdapter | Backend Python class designed to parse standard Revolut export formats. | revolut_csv.py:14-25 |
finalizeImport | Batches transactions and sends them to the backend for enrichment and insertion. | csv-import.ts:635-775 |
Column Mapping and AI Integration
The system supports a flexible ColumnMapping interface that translates raw CSV headers into structured transaction data.
Mapping Data Structure
The mapping configuration includes required fields (date, amount, description) and optional metadata (fees, states, balances).
export interface ColumnMapping {
date: string | null;
amount: string | null;
description: string | null;
merchant: string | null;
transactionType: string | null;
fee: string | null;
state: string | null;
startingBalance: string | null;
endingBalance: string | null;
typeConfig?: {
creditValue?: string;
debitValue?: string;
isAmountSigned?: boolean;
dateFormat?: "DD-MM-YYYY" | "MM-DD-YYYY";
completedStateValue?: string;
};
}
Sources: frontend/lib/actions/csv-import.ts:23-43, frontend/components/transactions/csv-mapping-table.tsx:21-29
AI Mapping Logic
When a user uploads a file, the getAiColumnMapping action sends the CSV headers and the first 3 sample rows to OpenAI. The AI is tasked with determining the date format (European vs. US), identifying which columns represent amounts or fees, and detecting the values used for "COMPLETED" status. Sources: frontend/lib/actions/csv-import.ts:172-220
Revolut-Specific Logic
Revolut imports utilize specialized parsing logic to handle the nuances of their CSV exports, such as "Paid Out" vs "Paid In" columns and specific transaction states.
Transaction Categorization
Revolut imports feature a hardcoded pattern-matching engine to automatically categorize transactions based on description keywords.
The diagram illustrates how the system matches specific merchant patterns to internal categories during Revolut-specific imports. Sources: frontend/lib/actions/csv-import.ts:881-940, frontend/scripts/import-revolut-csv.ts:85-105
Balance Verification
The system performs balance verification by comparing the "Ending Balance" column in the CSV with the calculated balance (Starting Balance + Sum of Transactions - Fees). A discrepancy check ensures the import is accurate before finalization. Sources: frontend/lib/actions/csv-import.ts:503-550
Implementation Details
Duplicate Prevention
To prevent redundant data, the system generates a deterministic external_id for every CSV transaction using a combination of FNV-1a, MurmurHash, and DJB2 algorithms. The hash is based on accountId, date, amount, description, and merchant. Sources: frontend/lib/actions/csv-import.ts:586-625
Backend Integration Endpoints
The frontend communicates with the backend via a secure internal API to finalize imports or enqueue them for background processing.
| Endpoint | Method | Purpose | Source |
|---|---|---|---|
/api/transactions/import | POST | Synchronous batch import of transaction items. | csv-import.ts:705 |
/api/csv-import/enqueue | POST | Enqueues import for Celery background processing. | csv-import.ts:842 |
/api/sync/revolut/csv | POST | Specific endpoint for raw Revolut CSV file sync. | REVOLUT_INTEGRATION.md:95-100 |
Sources: frontend/lib/actions/csv-import.ts:705-850, REVOLUT_INTEGRATION.md:95-105
Conclusion
The CSV and Revolut import module is a critical fallback for manual financial management. By combining flexible mapping tables, AI-assisted header detection, and robust deduplication logic, the system ensures that data imported from external files maintains the same integrity and categorization quality as data received via direct bank APIs. Sources: REVOLUT_INTEGRATION.md:15-30, BANK_INTEGRATION_GUIDE.md:90-110