From 6146d659cc8706c44d8daaf72367dd3dc9984915 Mon Sep 17 00:00:00 2001
From: Jed Fox <git@jedfox.com>
Date: Thu, 20 Jul 2023 06:19:18 -0400
Subject: [PATCH] Add support for parsing TSV files using the CSV logic (#1372)

---
 .../src/components/accounts/Account.js             |  5 ++++-
 .../src/components/modals/ImportTransactions.js    | 14 +++++++++++---
 .../loot-core/src/client/state-types/prefs.d.ts    |  2 +-
 .../loot-core/src/server/accounts/parse-file.ts    |  1 +
 upcoming-release-notes/1372.md                     |  6 ++++++
 5 files changed, 23 insertions(+), 5 deletions(-)
 create mode 100644 upcoming-release-notes/1372.md

diff --git a/packages/desktop-client/src/components/accounts/Account.js b/packages/desktop-client/src/components/accounts/Account.js
index e20366d8d..4b19fa501 100644
--- a/packages/desktop-client/src/components/accounts/Account.js
+++ b/packages/desktop-client/src/components/accounts/Account.js
@@ -416,7 +416,10 @@ class AccountInternal extends PureComponent {
     if (account) {
       const res = await window.Actual.openFileDialog({
         filters: [
-          { name: 'Financial Files', extensions: ['qif', 'ofx', 'qfx', 'csv'] },
+          {
+            name: 'Financial Files',
+            extensions: ['qif', 'ofx', 'qfx', 'csv', 'tsv'],
+          },
         ],
       });
 
diff --git a/packages/desktop-client/src/components/modals/ImportTransactions.js b/packages/desktop-client/src/components/modals/ImportTransactions.js
index cdec28e88..4165a49d5 100644
--- a/packages/desktop-client/src/components/modals/ImportTransactions.js
+++ b/packages/desktop-client/src/components/modals/ImportTransactions.js
@@ -117,7 +117,10 @@ function formatDate(date, format) {
 
 function getFileType(filepath) {
   let m = filepath.match(/\.([^.]*)$/);
-  return m ? m[1].toLowerCase() : 'ofx';
+  if (!m) return 'ofx';
+  let rawType = m[1].toLowerCase();
+  if (rawType === 'tsv') return 'csv';
+  return rawType;
 }
 
 function ParsedDate({ parseDateFormat, showParsed, dateFormat, date }) {
@@ -565,7 +568,8 @@ function ImportTransactions({
   // parsed different files without closing the modal, it wouldn't
   // re-read this.
   let [csvDelimiter, setCsvDelimiter] = useState(
-    prefs[`csv-delimiter-${accountId}`] || ',',
+    prefs[`csv-delimiter-${accountId}`] ||
+      (filename.endsWith('.tsv') ? '\t' : ','),
   );
 
   let [parseDateFormat, setParseDateFormat] = useState(null);
@@ -674,7 +678,10 @@ function ImportTransactions({
   async function onNewFile() {
     const res = await window.Actual.openFileDialog({
       filters: [
-        { name: 'Financial Files', extensions: ['qif', 'ofx', 'qfx', 'csv'] },
+        {
+          name: 'Financial Files',
+          extensions: ['qif', 'ofx', 'qfx', 'csv', 'tsv'],
+        },
       ],
     });
 
@@ -894,6 +901,7 @@ function ImportTransactions({
                     options={[
                       [',', ','],
                       [';', ';'],
+                      ['\t', 'tab'],
                     ]}
                     value={csvDelimiter}
                     onChange={value => {
diff --git a/packages/loot-core/src/client/state-types/prefs.d.ts b/packages/loot-core/src/client/state-types/prefs.d.ts
index 0ffd879d0..2bd95b03d 100644
--- a/packages/loot-core/src/client/state-types/prefs.d.ts
+++ b/packages/loot-core/src/client/state-types/prefs.d.ts
@@ -28,7 +28,7 @@ export type LocalPrefs = NullableValues<
     // TODO: pull from src/components/modals/ImportTransactions.js
     [key: `parse-date-${string}-${'csv' | 'qif'}`]: string;
     [key: `csv-mappings-${string}`]: string;
-    [key: `csv-delimiter-${string}`]: ',' | ';';
+    [key: `csv-delimiter-${string}`]: ',' | ';' | '\t';
     [key: `flip-amount-${string}-${'csv' | 'qif'}`]: boolean;
     'flags.updateNotificationShownForVersion': string;
     id: string;
diff --git a/packages/loot-core/src/server/accounts/parse-file.ts b/packages/loot-core/src/server/accounts/parse-file.ts
index 80e0e93a4..f1ffda03b 100644
--- a/packages/loot-core/src/server/accounts/parse-file.ts
+++ b/packages/loot-core/src/server/accounts/parse-file.ts
@@ -26,6 +26,7 @@ export async function parseFile(
       case '.qif':
         return parseQIF(filepath);
       case '.csv':
+      case '.tsv':
         return parseCSV(filepath, options);
       case '.ofx':
       case '.qfx':
diff --git a/upcoming-release-notes/1372.md b/upcoming-release-notes/1372.md
new file mode 100644
index 000000000..dfb4031ad
--- /dev/null
+++ b/upcoming-release-notes/1372.md
@@ -0,0 +1,6 @@
+---
+category: Enhancements
+authors: [j-f1]
+---
+
+Add support for parsing TSV files using the existing CSV parser
-- 
GitLab