1
0
Fork 0
mirror of https://github.com/maybe-finance/maybe.git synced 2025-07-22 06:39:39 +02:00

feat(import): add currency and number format support for CSV imports (#1819)
Some checks are pending
Publish Docker image / ci (push) Waiting to run
Publish Docker image / Build docker image (push) Blocked by required conditions

* feat(import): add currency and number format support for CSV imports

* feat(import): add currency and format for mint and trade

* fix(imports): remove currency field in favor of currency csv col

* fix(imports): remove validate column from import model

* test(import): add some tests for imports

* test(import): add some tests for generate_rows_from_csv

* fix: change method name for import model

* fix: change before validation

---------

Co-authored-by: danestves <danestves@users.noreply.github.com>
This commit is contained in:
Daniel Esteves 2025-02-10 16:31:28 -04:00 committed by GitHub
parent 9e5f1574bc
commit 077694bbde
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
9 changed files with 307 additions and 13 deletions

View file

@ -54,4 +54,233 @@ module ImportInterfaceTest
assert_equal "Failed to publish", import.error
assert_equal "failed", import.status
end
test "parses US/UK number format correctly" do
import = imports(:transaction)
import.update!(
number_format: "1,234.56",
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,name\n01/01/2024,\"1,234.56\",Test"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "1234.56", row.amount
end
test "parses European number format correctly" do
import = imports(:transaction)
import.update!(
number_format: "1.234,56",
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,name\n01/01/2024,\"1.234,56\",Test"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "1234.56", row.amount
end
test "parses French/Scandinavian number format correctly" do
import = imports(:transaction)
import.update!(
number_format: "1 234,56",
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
date_format: "%m/%d/%Y"
)
# Quote the amount field to ensure proper CSV parsing
csv_data = "date,amount,name\n01/01/2024,\"1 234,56\",Test"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "1234.56", row.amount
end
test "parses zero-decimal currency format correctly" do
import = imports(:transaction)
import.update!(
number_format: "1,234",
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,name\n01/01/2024,1234,Test"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "1234", row.amount
end
test "currency from CSV takes precedence over default" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
currency_col_label: "currency",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
import.family.update!(currency: "USD")
csv_data = "date,amount,name,currency\n01/01/2024,123.45,Test,EUR"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "EUR", row.currency
end
test "uses default currency when CSV currency column is empty" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
currency_col_label: "currency",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
import.family.update!(currency: "USD")
csv_data = "date,amount,name,currency\n01/01/2024,123.45,Test,"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "USD", row.currency
end
test "uses default currency when CSV has no currency column" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
import.family.update!(currency: "USD")
csv_data = "date,amount,name\n01/01/2024,123.45,Test"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "USD", row.currency
end
test "generates rows with all optional fields" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
account_col_label: "account",
category_col_label: "category",
tags_col_label: "tags",
notes_col_label: "notes",
currency_col_label: "currency",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,name,account,category,tags,notes,currency\n" \
"01/01/2024,1234.56,Salary,Bank Account,Income,\"monthly,salary\",Salary payment,EUR"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "01/01/2024", row.date
assert_equal "1234.56", row.amount
assert_equal "Salary", row.name
assert_equal "Bank Account", row.account
assert_equal "Income", row.category
assert_equal "monthly,salary", row.tags
assert_equal "Salary payment", row.notes
assert_equal "EUR", row.currency
end
test "generates rows with minimal required fields" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount\n01/01/2024,1234.56"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "01/01/2024", row.date
assert_equal "1234.56", row.amount
assert_equal "Imported item", row.name # Default name
assert_equal import.family.currency, row.currency # Default currency
end
test "handles empty values in optional fields" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
name_col_label: "name",
category_col_label: "category",
tags_col_label: "tags",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,name,category,tags\n01/01/2024,1234.56,,,"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "01/01/2024", row.date
assert_equal "1234.56", row.amount
assert_equal "Imported item", row.name # Falls back to default
assert_equal "", row.category
assert_equal "", row.tags
end
test "handles trade-specific fields" do
import = imports(:transaction)
import.update!(
amount_col_label: "amount",
date_col_label: "date",
qty_col_label: "quantity",
ticker_col_label: "symbol",
price_col_label: "price",
number_format: "1,234.56",
date_format: "%m/%d/%Y"
)
csv_data = "date,amount,quantity,symbol,price\n01/01/2024,1234.56,10,AAPL,123.456"
import.update!(raw_file_str: csv_data)
import.generate_rows_from_csv
row = import.rows.first
assert_equal "10", row.qty
assert_equal "AAPL", row.ticker
assert_equal "123.456", row.price
end
end