{% extends "base.html" %} {% block title %}Import Transactions{% endblock %} {% block page_title %}Import CSV{% endblock %} {% block topbar_actions %} Settings {% endblock %} {% block content %}
Upload CSV File
Required CSV format:
date,type,description,category,account,amount,notes
2025-01-15,expense,Groceries,Food & Dining,Checking,85.50,Weekly shop
2025-01-16,income,Salary,Salary,Checking,3000.00,
Required: date, type (income/expense), description, amount
Optional: category, account, notes
Date formats: YYYY-MM-DD, MM/DD/YYYY, DD/MM/YYYY
{{ form.hidden_tag() }}
{{ form.csv_file.label(class="form-label fw-medium", style="font-size:13px;") }} {{ form.csv_file(class="form-control" + (" is-invalid" if form.csv_file.errors else "")) }} {% for e in form.csv_file.errors %}
{{ e }}
{% endfor %}
{{ form.default_account_id.label(class="form-label fw-medium", style="font-size:13px;") }} {{ form.default_account_id(class="form-select") }} Used when account column is missing or unrecognised.
{{ form.skip_duplicates(class="form-check-input") }} {{ form.skip_duplicates.label(class="form-check-label", style="font-size:13px;") }}
{{ form.submit(class="btn btn-primary") }}
{% if parse_errors %}
Parse Errors
{% for err in parse_errors %}
{{ err }}
{% endfor %}
{% endif %} {% if preview %}
Preview — {{ preview | length }} rows ready to import
{% for row in preview[:20] %} {% endfor %} {% if preview | length > 20 %} {% endif %}
Date Type Description Category Account Amount
{{ row.date.strftime('%b %d, %Y') }} {{ row.transaction_type | title }} {{ row.description }} {{ row.category_name or '—' }} {% if row.category_name and not row.category_id %} {% endif %} {{ row.account_name or '—' }} {% if not row.account_id %} {% endif %} {{ row.amount | currency }}
... and {{ (preview | length) - 20 }} more rows
{% endif %}
{% endblock %}