-
Notifications
You must be signed in to change notification settings - Fork 0
/
CSVImporter.swift
69 lines (58 loc) · 1.69 KB
/
CSVImporter.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
//
// CSVImporter.swift
// SwiftBeanCountImporter
//
// Created by Steffen Kötte on 2020-05-10.
// Copyright © 2020 Steffen Kötte. All rights reserved.
//
import CSV
import Foundation
import SwiftBeanCountModel
struct CSVLine {
let date: Date
let description: String
let amount: Decimal
let payee: String
let price: Amount?
}
enum CSVImporterFactory {
static var importers: [CSVImporter.Type] {
[
RBCImporter.self,
TangerineCardImporter.self,
TangerineAccountImporter.self,
LunchOnUsImporter.self,
N26Importer.self,
RogersImporter.self,
SimpliiImporter.self,
CompassCardImporter.self
]
}
static func new(ledger: Ledger?, url: URL?) -> FileImporter? {
guard let url, let csvReader = openFile(url), let headerRow = csvReader.headerRow else {
return nil
}
let importer = Self.importers.first {
$0.headers.contains(headerRow)
}
guard let importerClass = importer else {
return nil
}
return importerClass.init(ledger: ledger, csvReader: csvReader, fileName: url.lastPathComponent)
}
private static func openFile(_ url: URL) -> CSVReader? {
let inputStream = InputStream(url: url)
guard let input = inputStream else {
return nil
}
do {
return try CSVReader(stream: input, hasHeaderRow: true, trimFields: true)
} catch {
return nil
}
}
}
protocol CSVImporter: FileImporter {
static var headers: [[String]] { get }
init(ledger: Ledger?, csvReader: CSVReader, fileName: String)
}