From 9090c5c2232a5288c1f168763ea39484387ec3a3 Mon Sep 17 00:00:00 2001 From: MaysWind Date: Sun, 15 Jun 2025 22:59:21 +0800 Subject: [PATCH] set geo location data order when import transaction --- pkg/api/transactions.go | 9 ++- ...eancount_transaction_data_file_importer.go | 2 +- .../data_table_transaction_data_importer.go | 23 ++++++- ...t_transaction_data_plain_text_converter.go | 2 + ...stom_transaction_data_dsv_file_importer.go | 13 +++- ...transaction_data_dsv_file_importer_test.go | 64 +++++++++---------- ...yiii_transaction_data_csv_file_importer.go | 2 +- pkg/converters/transaction_data_converters.go | 4 +- src/lib/services.ts | 3 +- src/locales/de.json | 2 + src/locales/en.json | 2 + src/locales/es.json | 2 + src/locales/it.json | 2 + src/locales/ja.json | 2 + src/locales/ru.json | 2 + src/locales/uk.json | 2 + src/locales/vi.json | 2 + src/locales/zh_Hans.json | 2 + src/locales/zh_Hant.json | 2 + src/stores/transaction.ts | 4 +- .../transactions/import/ImportDialog.vue | 42 +++++++++--- 21 files changed, 133 insertions(+), 55 deletions(-) diff --git a/pkg/api/transactions.go b/pkg/api/transactions.go index f9da48b8..4f7d18d0 100644 --- a/pkg/api/transactions.go +++ b/pkg/api/transactions.go @@ -1219,6 +1219,13 @@ func (a *TransactionsApi) TransactionParseImportFileHandler(c *core.WebContext) geoLocationSeparator = geoLocationSeparators[0] } + geoLocationOrders := form.Value["geoOrder"] + geoLocationOrder := "" + + if len(geoLocationOrders) > 0 { + geoLocationOrder = geoLocationOrders[0] + } + transactionTagSeparators := form.Value["tagSeparator"] transactionTagSeparator := "" @@ -1226,7 +1233,7 @@ func (a *TransactionsApi) TransactionParseImportFileHandler(c *core.WebContext) transactionTagSeparator = transactionTagSeparators[0] } - dataImporter, err = converters.CreateNewDelimiterSeparatedValuesDataImporter(fileType, fileEncoding, columnIndexMapping, transactionTypeNameMapping, hasHeaderLine, timeFormats[0], timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoLocationSeparator, transactionTagSeparator) + dataImporter, err = converters.CreateNewDelimiterSeparatedValuesDataImporter(fileType, fileEncoding, columnIndexMapping, transactionTypeNameMapping, hasHeaderLine, timeFormats[0], timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoLocationSeparator, geoLocationOrder, transactionTagSeparator) } else { dataImporter, err = converters.GetTransactionDataImporter(fileType) } diff --git a/pkg/converters/beancount/beancount_transaction_data_file_importer.go b/pkg/converters/beancount/beancount_transaction_data_file_importer.go index 41287880..71e67149 100644 --- a/pkg/converters/beancount/beancount_transaction_data_file_importer.go +++ b/pkg/converters/beancount/beancount_transaction_data_file_importer.go @@ -43,7 +43,7 @@ func (c *beancountTransactionDataImporter) ParseImportedData(ctx core.Context, u return nil, nil, nil, nil, nil, nil, err } - dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(beancountTransactionTypeNameMapping, "", BEANCOUNT_TRANSACTION_TAG_SEPARATOR) + dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(beancountTransactionTypeNameMapping, "", "", BEANCOUNT_TRANSACTION_TAG_SEPARATOR) return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/converter/data_table_transaction_data_importer.go b/pkg/converters/converter/data_table_transaction_data_importer.go index d66ede3e..0f8bfd3c 100644 --- a/pkg/converters/converter/data_table_transaction_data_importer.go +++ b/pkg/converters/converter/data_table_transaction_data_importer.go @@ -13,10 +13,18 @@ import ( "github.com/mayswind/ezbookkeeping/pkg/validators" ) +type TransactionGeoLocationOrder string + +const ( + TRANSACTION_GEO_LOCATION_ORDER_LONGITUDE_LATITUDE TransactionGeoLocationOrder = "lonlat" // longitude first, then latitude + TRANSACTION_GEO_LOCATION_ORDER_LATITUDE_LONGITUDE TransactionGeoLocationOrder = "latlon" // latitude first, then longitude +) + // DataTableTransactionDataImporter defines the structure of plain text data table importer for transaction data type DataTableTransactionDataImporter struct { transactionTypeMapping map[string]models.TransactionType geoLocationSeparator string + geoLocationOrder TransactionGeoLocationOrder transactionTagSeparator string } @@ -268,19 +276,27 @@ func (c *DataTableTransactionDataImporter) ParseImportedData(ctx core.Context, u geoLocationItems := strings.Split(dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION), c.geoLocationSeparator) if len(geoLocationItems) == 2 { - geoLongitude, err = utils.StringToFloat64(geoLocationItems[0]) + geoLocationFirstItem, err := utils.StringToFloat64(geoLocationItems[0]) if err != nil { log.Errorf(ctx, "[data_table_transaction_data_exporter.ParseImportedData] cannot parse geographic location \"%s\" in data row \"index:%d\" for user \"uid:%d\", because %s", dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION), dataRowIndex, user.Uid, err.Error()) return nil, nil, nil, nil, nil, nil, errs.ErrGeographicLocationInvalid } - geoLatitude, err = utils.StringToFloat64(geoLocationItems[1]) + geoLocationSecondItem, err := utils.StringToFloat64(geoLocationItems[1]) if err != nil { log.Errorf(ctx, "[data_table_transaction_data_exporter.ParseImportedData] cannot parse geographic location \"%s\" in data row \"index:%d\" for user \"uid:%d\", because %s", dataRow.GetData(datatable.TRANSACTION_DATA_TABLE_GEOGRAPHIC_LOCATION), dataRowIndex, user.Uid, err.Error()) return nil, nil, nil, nil, nil, nil, errs.ErrGeographicLocationInvalid } + + if c.geoLocationOrder == TRANSACTION_GEO_LOCATION_ORDER_LONGITUDE_LATITUDE { + geoLongitude = geoLocationFirstItem + geoLatitude = geoLocationSecondItem + } else if c.geoLocationOrder == TRANSACTION_GEO_LOCATION_ORDER_LATITUDE_LONGITUDE { + geoLatitude = geoLocationFirstItem + geoLongitude = geoLocationSecondItem + } } } @@ -466,10 +482,11 @@ func (c *DataTableTransactionDataImporter) createNewTransactionTagModel(uid int6 } // CreateNewImporterWithTypeNameMapping returns a new data table transaction data importer according to the specified arguments -func CreateNewImporterWithTypeNameMapping(transactionTypeMapping map[models.TransactionType]string, geoLocationSeparator string, transactionTagSeparator string) *DataTableTransactionDataImporter { +func CreateNewImporterWithTypeNameMapping(transactionTypeMapping map[models.TransactionType]string, geoLocationSeparator string, geoLocationOrder TransactionGeoLocationOrder, transactionTagSeparator string) *DataTableTransactionDataImporter { return &DataTableTransactionDataImporter{ transactionTypeMapping: buildTransactionNameTypeMap(transactionTypeMapping), geoLocationSeparator: geoLocationSeparator, + geoLocationOrder: geoLocationOrder, transactionTagSeparator: transactionTagSeparator, } } diff --git a/pkg/converters/default/default_transaction_data_plain_text_converter.go b/pkg/converters/default/default_transaction_data_plain_text_converter.go index f655be09..7e61abc8 100644 --- a/pkg/converters/default/default_transaction_data_plain_text_converter.go +++ b/pkg/converters/default/default_transaction_data_plain_text_converter.go @@ -14,6 +14,7 @@ type defaultTransactionDataPlainTextConverter struct { const ezbookkeepingLineSeparator = "\n" const ezbookkeepingGeoLocationSeparator = " " +const ezbookkeepingGeoLocationOrder = converter.TRANSACTION_GEO_LOCATION_ORDER_LONGITUDE_LATITUDE const ezbookkeepingTagSeparator = ";" var ezbookkeepingDataColumnNameMapping = map[datatable.TransactionDataTableColumn]string{ @@ -99,6 +100,7 @@ func (c *defaultTransactionDataPlainTextConverter) ParseImportedData(ctx core.Co dataTableImporter := converter.CreateNewImporterWithTypeNameMapping( ezbookkeepingTransactionTypeNameMapping, ezbookkeepingGeoLocationSeparator, + ezbookkeepingGeoLocationOrder, ezbookkeepingTagSeparator, ) diff --git a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go index 7cf73001..4164add4 100644 --- a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go +++ b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer.go @@ -106,6 +106,7 @@ type customTransactionDataDsvFileImporter struct { amountDecimalSeparator string amountDigitGroupingSymbol string geoLocationSeparator string + geoLocationOrder converter.TransactionGeoLocationOrder transactionTagSeparator string } @@ -158,7 +159,7 @@ func (c *customTransactionDataDsvFileImporter) ParseImportedData(ctx core.Contex dataTable := csvconverter.CreateNewCustomCsvImportedDataTable(allLines) transactionDataTable := CreateNewCustomPlainTextDataTable(dataTable, c.columnIndexMapping, c.transactionTypeNameMapping, c.timeFormat, c.timezoneFormat, c.amountDecimalSeparator, c.amountDigitGroupingSymbol) - dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(customTransactionTypeNameMapping, c.geoLocationSeparator, c.transactionTagSeparator) + dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(customTransactionTypeNameMapping, c.geoLocationSeparator, c.geoLocationOrder, c.transactionTagSeparator) return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } @@ -190,7 +191,7 @@ func CreateNewCustomTransactionDataDsvFileParser(fileType string, fileEncoding s } // CreateNewCustomTransactionDataDsvFileImporter returns a new custom dsv importer for transaction data -func CreateNewCustomTransactionDataDsvFileImporter(fileType string, fileEncoding string, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, hasHeaderLine bool, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string, geoLocationSeparator string, transactionTagSeparator string) (converter.TransactionDataImporter, error) { +func CreateNewCustomTransactionDataDsvFileImporter(fileType string, fileEncoding string, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, hasHeaderLine bool, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string, geoLocationSeparator string, geoLocationOrder string, transactionTagSeparator string) (converter.TransactionDataImporter, error) { separator, exists := supportedFileTypeSeparators[fileType] if !exists { @@ -203,6 +204,13 @@ func CreateNewCustomTransactionDataDsvFileImporter(fileType string, fileEncoding return nil, errs.ErrImportFileEncodingNotSupported } + if geoLocationOrder == "" { + geoLocationOrder = string(converter.TRANSACTION_GEO_LOCATION_ORDER_LONGITUDE_LATITUDE) + } else if geoLocationOrder != string(converter.TRANSACTION_GEO_LOCATION_ORDER_LONGITUDE_LATITUDE) && + geoLocationOrder != string(converter.TRANSACTION_GEO_LOCATION_ORDER_LATITUDE_LONGITUDE) { + return nil, errs.ErrImportFileTypeNotSupported + } + if _, exists = columnIndexMapping[datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME]; !exists { return nil, errs.ErrMissingRequiredFieldInHeaderRow } @@ -226,6 +234,7 @@ func CreateNewCustomTransactionDataDsvFileImporter(fileType string, fileEncoding amountDecimalSeparator: amountDecimalSeparator, amountDigitGroupingSymbol: amountDigitGroupingSymbol, geoLocationSeparator: geoLocationSeparator, + geoLocationOrder: converter.TransactionGeoLocationOrder(geoLocationOrder), transactionTagSeparator: transactionTagSeparator, }, nil } diff --git a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go index 34480949..e2baeb70 100644 --- a/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go +++ b/pkg/converters/dsv/custom_transaction_data_dsv_file_importer_test.go @@ -77,7 +77,7 @@ func TestCustomTransactionDataDsvFileImporter_MinimumValidData(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", ".", "", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", ".", "", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -168,7 +168,7 @@ func TestCustomTransactionDataDsvFileImporter_WithAllSupportedColumns(t *testing "Expense": models.TRANSACTION_TYPE_EXPENSE, "Transfer": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, true, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", ";") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, true, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", ";") assert.Nil(t, err) context := core.NewNullContext() @@ -261,7 +261,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTime(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -292,7 +292,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTransactionWithoutType(t *tes "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -316,7 +316,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidType(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "B": 0, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -340,7 +340,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone(t *testing.T transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZ", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZ", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -378,7 +378,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTimeWithTimezone2(t *testing. transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZZ", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ssZZ", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -417,7 +417,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -456,7 +456,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidTimezone2(t *testing.T) transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -495,7 +495,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezoneFormat(t *test transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "z", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "z", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -520,7 +520,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone(t *testing.T) transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -549,7 +549,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidTimezone2(t *testing.T transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "ZZ", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -577,7 +577,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseAmountWithCustomFormat(t *tes transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", ".", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", ".", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -603,7 +603,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", ",", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", ",", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -627,7 +627,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmountWithCustomFormat transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_tsv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ",", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -655,7 +655,7 @@ func TestCustomTransactionDataDsvFileImporter_ParsePrimaryCategory(t *testing.T) "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -724,7 +724,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAccountCurrency(t *testi "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -767,7 +767,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAccountCurrency(t *tes "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -803,7 +803,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseNotSupportedCurrency(t *testi "B": models.TRANSACTION_TYPE_MODIFY_BALANCE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -835,7 +835,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidAmount(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -886,7 +886,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidAmount(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -917,7 +917,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseNoAmount2(t *testing.T) { "E": models.TRANSACTION_TYPE_EXPENSE, "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -952,7 +952,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseValidGeographicLocation(t *te transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", ";", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", ";", "lonlat", "") assert.Nil(t, err) context := core.NewNullContext() @@ -981,7 +981,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseInvalidGeographicLocation(t * transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", " ", "lonlat", "") assert.Nil(t, err) context := core.NewNullContext() @@ -1013,7 +1013,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTag(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", ";") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", ";") assert.Nil(t, err) context := core.NewNullContext() @@ -1053,7 +1053,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseTagWithoutSeparator(t *testin transactionTypeMapping := map[string]models.TransactionType{ "E": models.TRANSACTION_TYPE_EXPENSE, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -1084,7 +1084,7 @@ func TestCustomTransactionDataDsvFileImporter_ParseDescription(t *testing.T) { transactionTypeMapping := map[string]models.TransactionType{ "T": models.TRANSACTION_TYPE_TRANSFER, } - converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + converter, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.Nil(t, err) context := core.NewNullContext() @@ -1111,7 +1111,7 @@ func TestCustomTransactionDataDsvFileImporter_InvalidSeparator(t *testing.T) { datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: 1, datatable.TRANSACTION_DATA_TABLE_AMOUNT: 2, } - _, err := CreateNewCustomTransactionDataDsvFileImporter("test", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + _, err := CreateNewCustomTransactionDataDsvFileImporter("test", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.EqualError(t, err, errs.ErrImportFileTypeNotSupported.Message) } @@ -1124,7 +1124,7 @@ func TestCustomTransactionDataDsvFileImporter_InvalidFileEncoding(t *testing.T) datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: 1, datatable.TRANSACTION_DATA_TABLE_AMOUNT: 2, } - _, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "ascii", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + _, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "ascii", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.EqualError(t, err, errs.ErrImportFileEncodingNotSupported.Message) } @@ -1138,7 +1138,7 @@ func TestCustomTransactionDataDsvFileImporter_MissingRequiredColumn(t *testing.T datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: 0, datatable.TRANSACTION_DATA_TABLE_AMOUNT: 1, } - _, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + _, err := CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Type Column @@ -1146,7 +1146,7 @@ func TestCustomTransactionDataDsvFileImporter_MissingRequiredColumn(t *testing.T datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME: 0, datatable.TRANSACTION_DATA_TABLE_AMOUNT: 1, } - _, err = CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + _, err = CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) // Missing Amount Column @@ -1154,6 +1154,6 @@ func TestCustomTransactionDataDsvFileImporter_MissingRequiredColumn(t *testing.T datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TIME: 0, datatable.TRANSACTION_DATA_TABLE_TRANSACTION_TYPE: 1, } - _, err = CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "") + _, err = CreateNewCustomTransactionDataDsvFileImporter("custom_csv", "utf-8", columnIndexMapping, transactionTypeMapping, false, "YYYY-MM-DD HH:mm:ss", "", ".", "", "", "", "") assert.EqualError(t, err, errs.ErrMissingRequiredFieldInHeaderRow.Message) } diff --git a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go index 808f4b45..706050b4 100644 --- a/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go +++ b/pkg/converters/fireflyIII/fireflyiii_transaction_data_csv_file_importer.go @@ -50,7 +50,7 @@ func (c *fireflyIIITransactionDataCsvFileImporter) ParseImportedData(ctx core.Co transactionRowParser := createFireflyIIITransactionDataRowParser() transactionDataTable := datatable.CreateNewImportedTransactionDataTableWithRowParser(dataTable, fireflyIIITransactionDataColumnNameMapping, transactionRowParser) - dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(fireflyIIITransactionTypeNameMapping, "", ",") + dataTableImporter := converter.CreateNewImporterWithTypeNameMapping(fireflyIIITransactionTypeNameMapping, "", "", ",") return dataTableImporter.ParseImportedData(ctx, user, transactionDataTable, defaultTimezoneOffset, accountMap, expenseCategoryMap, incomeCategoryMap, transferCategoryMap, tagMap) } diff --git a/pkg/converters/transaction_data_converters.go b/pkg/converters/transaction_data_converters.go index 82a98176..6fe9a39b 100644 --- a/pkg/converters/transaction_data_converters.go +++ b/pkg/converters/transaction_data_converters.go @@ -81,6 +81,6 @@ func CreateNewDelimiterSeparatedValuesDataParser(fileType string, fileEncoding s } // CreateNewDelimiterSeparatedValuesDataImporter returns a new delimiter-separated values data importer according to the file type and encoding -func CreateNewDelimiterSeparatedValuesDataImporter(fileType string, fileEncoding string, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, hasHeaderLine bool, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string, geoLocationSeparator string, transactionTagSeparator string) (converter.TransactionDataImporter, error) { - return dsv.CreateNewCustomTransactionDataDsvFileImporter(fileType, fileEncoding, columnIndexMapping, transactionTypeNameMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoLocationSeparator, transactionTagSeparator) +func CreateNewDelimiterSeparatedValuesDataImporter(fileType string, fileEncoding string, columnIndexMapping map[datatable.TransactionDataTableColumn]int, transactionTypeNameMapping map[string]models.TransactionType, hasHeaderLine bool, timeFormat string, timezoneFormat string, amountDecimalSeparator string, amountDigitGroupingSymbol string, geoLocationSeparator string, geoLocationOrder string, transactionTagSeparator string) (converter.TransactionDataImporter, error) { + return dsv.CreateNewCustomTransactionDataDsvFileImporter(fileType, fileEncoding, columnIndexMapping, transactionTypeNameMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoLocationSeparator, geoLocationOrder, transactionTagSeparator) } diff --git a/src/lib/services.ts b/src/lib/services.ts index 9a8ed72f..12bbba83 100644 --- a/src/lib/services.ts +++ b/src/lib/services.ts @@ -447,7 +447,7 @@ export default { timeout: DEFAULT_UPLOAD_API_TIMEOUT } as ApiRequestConfig); }, - parseImportTransaction: ({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, tagSeparator?: string }): ApiResponsePromise => { + parseImportTransaction: ({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): ApiResponsePromise => { let textualColumnMapping: string | undefined = undefined; let textualTransactionTypeMapping: string | undefined = undefined; let textualHasHeaderLine: string | undefined = undefined; @@ -476,6 +476,7 @@ export default { amountDecimalSeparator: amountDecimalSeparator, amountDigitGroupingSymbol: amountDigitGroupingSymbol, geoSeparator: geoSeparator, + geoOrder: geoOrder, tagSeparator: tagSeparator }, { timeout: DEFAULT_UPLOAD_API_TIMEOUT diff --git a/src/locales/de.json b/src/locales/de.json index 8b8afc6d..64787770 100644 --- a/src/locales/de.json +++ b/src/locales/de.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Gleiche Zeit wie Standardzeitzone", "Transaction Type": "Transaction Type", "Geographic Location": "Geografischer Standort", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Kein Standort", "Getting Location...": "Standort wird ermittelt...", "Show on the map": "Auf der Karte anzeigen", diff --git a/src/locales/en.json b/src/locales/en.json index 2a598bf2..da979f5c 100644 --- a/src/locales/en.json +++ b/src/locales/en.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Same time as default timezone", "Transaction Type": "Transaction Type", "Geographic Location": "Geographic Location", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "No Location", "Getting Location...": "Getting Location...", "Show on the map": "Show on the map", diff --git a/src/locales/es.json b/src/locales/es.json index 54f08bce..3b1fe7f1 100644 --- a/src/locales/es.json +++ b/src/locales/es.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Misma hora que la zona horaria predeterminada", "Transaction Type": "Transaction Type", "Geographic Location": "Ubicación geográfica", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Sin ubicación", "Getting Location...": "Obteniendo ubicación...", "Show on the map": "Mostrar en el mapa", diff --git a/src/locales/it.json b/src/locales/it.json index 0d41f650..33650bea 100644 --- a/src/locales/it.json +++ b/src/locales/it.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Stessa ora del fuso orario predefinito", "Transaction Type": "Tipo di transazione", "Geographic Location": "Posizione geografica", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Nessuna posizione", "Getting Location...": "Recupero posizione...", "Show on the map": "Mostra sulla mappa", diff --git a/src/locales/ja.json b/src/locales/ja.json index 8512f6b8..bf8f3bc7 100644 --- a/src/locales/ja.json +++ b/src/locales/ja.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "デフォルトのタイムゾーンと同じ時間", "Transaction Type": "取引タイプ", "Geographic Location": "地理座標", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "座標はありません", "Getting Location...": "座標を取得中...", "Show on the map": "マップに表示", diff --git a/src/locales/ru.json b/src/locales/ru.json index 7b91b706..c695b90b 100644 --- a/src/locales/ru.json +++ b/src/locales/ru.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "То же время, что и в часовом поясе по умолчанию", "Transaction Type": "Transaction Type", "Geographic Location": "Географическое местоположение", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Нет местоположения", "Getting Location...": "Получение местоположения...", "Show on the map": "Показать на карте", diff --git a/src/locales/uk.json b/src/locales/uk.json index fc2c0ac3..da1f9151 100644 --- a/src/locales/uk.json +++ b/src/locales/uk.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Той самий час, що й у часовому поясі за замовчуванням", "Transaction Type": "Тип транзакції", "Geographic Location": "Географічне розташування", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Немає розташування", "Getting Location...": "Отримання розташування...", "Show on the map": "Показати на карті", diff --git a/src/locales/vi.json b/src/locales/vi.json index 1a65e123..fbadba95 100644 --- a/src/locales/vi.json +++ b/src/locales/vi.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "Cùng thời gian với múi giờ mặc định", "Transaction Type": "Transaction Type", "Geographic Location": "Vị trí địa lý", + "Longitude": "Longitude", + "Latitude": "Latitude", "No Location": "Không có vị trí", "Getting Location...": "Đang lấy vị trí...", "Show on the map": "Hiển thị trên bản đồ", diff --git a/src/locales/zh_Hans.json b/src/locales/zh_Hans.json index 6c3bb8b6..2c438f82 100644 --- a/src/locales/zh_Hans.json +++ b/src/locales/zh_Hans.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "与默认时区时间相同", "Transaction Type": "交易类型", "Geographic Location": "地理位置", + "Longitude": "经度", + "Latitude": "纬度", "No Location": "没有位置", "Getting Location...": "正在获取位置...", "Show on the map": "在地图上显示", diff --git a/src/locales/zh_Hant.json b/src/locales/zh_Hant.json index b9c2b1f9..26b43cf4 100644 --- a/src/locales/zh_Hant.json +++ b/src/locales/zh_Hant.json @@ -1657,6 +1657,8 @@ "Same time as default timezone": "與預設時區時間相同", "Transaction Type": "交易類型", "Geographic Location": "地理位置", + "Longitude": "經度", + "Latitude": "緯度", "No Location": "沒有位置", "Getting Location...": "正在取得位置...", "Show on the map": "在地圖上顯示", diff --git a/src/stores/transaction.ts b/src/stores/transaction.ts index b46e7c50..c3ce8ec7 100644 --- a/src/stores/transaction.ts +++ b/src/stores/transaction.ts @@ -1129,9 +1129,9 @@ export const useTransactionsStore = defineStore('transactions', () => { }); } - function parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, tagSeparator?: string }): Promise { + function parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }: { fileType: string, fileEncoding?: string, importFile: File, columnMapping?: Record, transactionTypeMapping?: Record, hasHeaderLine?: boolean, timeFormat?: string, timezoneFormat?: string, amountDecimalSeparator?: string, amountDigitGroupingSymbol?: string, geoSeparator?: string, geoOrder?: string, tagSeparator?: string }): Promise { return new Promise((resolve, reject) => { - services.parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, tagSeparator }).then(response => { + services.parseImportTransaction({ fileType, fileEncoding, importFile, columnMapping, transactionTypeMapping, hasHeaderLine, timeFormat, timezoneFormat, amountDecimalSeparator, amountDigitGroupingSymbol, geoSeparator, geoOrder, tagSeparator }).then(response => { const data = response.data; if (!data || !data.success || !data.result) { diff --git a/src/views/desktop/transactions/import/ImportDialog.vue b/src/views/desktop/transactions/import/ImportDialog.vue index 6ceeb738..be338e32 100644 --- a/src/views/desktop/transactions/import/ImportDialog.vue +++ b/src/views/desktop/transactions/import/ImportDialog.vue @@ -424,16 +424,33 @@ {{ tt('Geographic Location Separator') }} - ({{ parsedFileGeoLocationSeparator }}) - - - - - {{ separator.name }} ({{separator.value}}) - + ({{ parsedFileGeoLocationOrder === 'latlon' ? `${tt('Latitude')}${parsedFileGeoLocationSeparator}${tt('Longitude')}` : `${tt('Longitude')}${parsedFileGeoLocationSeparator}${tt('Latitude')}` }}) + + + + + + + {{ separator.name }} ({{separator.value}}) + + + {{ `${tt('Latitude')}${separator.value}${tt('Longitude')}` }} + {{ `${tt('Longitude')}${separator.value}${tt('Latitude')}` }} + + + {{ `${tt('Latitude')}${separator.value}${tt('Longitude')}` }} + {{ `${tt('Longitude')}${separator.value}${tt('Latitude')}` }} + + + + + @@ -986,6 +1003,7 @@ const parsedFileTimeFormat = ref(''); const parsedFileTimezoneFormat = ref(''); const parsedFileAmountFormat = ref(''); const parsedFileGeoLocationSeparator = ref(' '); +const parsedFileGeoLocationOrder = ref('lonlat'); const parsedFileTagSeparator = ref(';'); const importTransactions = ref(undefined); const editingTransaction = ref(null); @@ -1943,6 +1961,7 @@ function open(): Promise { parsedFileTimezoneFormat.value = ''; parsedFileAmountFormat.value = ''; parsedFileGeoLocationSeparator.value = ' '; + parsedFileGeoLocationOrder.value = 'lonlat'; parsedFileTagSeparator.value = ';'; importTransactions.value = undefined; editingTransaction.value = null; @@ -2088,6 +2107,7 @@ function parseData(): void { let amountDecimalSeparator: string | undefined = undefined; let amountDigitGroupingSymbol: string | undefined = undefined; let geoLocationSeparator: string | undefined = undefined; + let geoLocationOrder: string | undefined = undefined; let tagSeparator: string | undefined = undefined; if (isDsvFileType) { @@ -2098,6 +2118,7 @@ function parseData(): void { timezoneFormat = parsedFileTimezoneFormat.value; amountFormat = parsedFileAmountFormat.value; geoLocationSeparator = parsedFileGeoLocationSeparator.value; + geoLocationOrder = parsedFileGeoLocationOrder.value; tagSeparator = parsedFileTagSeparator.value; if (!columnMapping @@ -2159,6 +2180,7 @@ function parseData(): void { amountDecimalSeparator: amountDecimalSeparator, amountDigitGroupingSymbol: amountDigitGroupingSymbol, geoSeparator: geoLocationSeparator, + geoOrder: geoLocationOrder, tagSeparator: tagSeparator }).then(response => { const parsedTransactions: ImportTransaction[] = [];