-
Notifications
You must be signed in to change notification settings - Fork 0
/
Settings.swift
156 lines (137 loc) · 6.4 KB
/
Settings.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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
//
// Settings.swift
// SwiftBeanCountImporter
//
// Created by Steffen Kötte on 2020-05-10.
// Copyright © 2020 Steffen Kötte. All rights reserved.
//
import Foundation
/// Protocol to define a storage for the settings
public protocol SettingsStorage {
/// Saves a value for a key
func set(_ value: Any?, forKey defaultName: String)
/// Gets a saved string for a given key
func string(forKey defaultName: String) -> String?
/// Gets a saved dictionary for a given key
func dictionary(forKey defaultName: String) -> [String: Any]? // swiftlint:disable:this discouraged_optional_collection
}
/// Constants releated to settings of the importer
public enum Settings {
/// Storage key for the payee mapping
private static let payeesKey = "payees"
/// Storage key for the account mapping
private static let accountsKey = "accounts"
/// Storage key for the description mapping
private static let descriptionKey = "description"
/// Storage key for the date tolerance to detect duplicate transactions
private static let dateToleranceKey = "date_tolerance"
/// Default date tolerance to detect duplicate transactions
static let defaultDateTolerance = 2 // days
// Default account name to book the other posting of an imported transaction to
static let defaultAccountName = "Expenses:TODO"
/// Currency to use if the account does not have a currency specified
static let fallbackCommodity = "CAD"
/// Key used to save the importer type into the metaData of an account
static let importerTypeKey = "importer-type"
/// A Storage which saves the settings
///
/// Default value is `UserDefaults.standard`
public static var storage: SettingsStorage = UserDefaults.standard
/// Mappings of descriptions the user saved when importing previous transactions
///
/// These are automatically applied when importing and are only exported to allow apps
/// to offer a settings screen to view and modify them.
///
/// Keys are the original descriptions from the importer and the value are the new descriptions
/// the user mapped them to
public static var allDescriptionMappings: [String: String] {
storage.dictionary(forKey: descriptionKey) as? [String: String] ?? [:]
}
/// Mappings of payees the user saved when importing previous transactions
///
/// These are automatically applied when importing and are only exported to allow apps
/// to offer a settings screen to view and modify them.
///
/// Keys are the original descriptions from the importer and the values are the new payees
/// the user mapped them to
public static var allPayeeMappings: [String: String] {
storage.dictionary(forKey: payeesKey) as? [String: String] ?? [:]
}
/// Mappings of accounts the user saved when importing previous transactions
///
/// These are automatically applied when importing and are only exported to allow apps
/// to offer a settings screen to view and modify them.
///
/// Keys are payees and the values are account name strings the user mapped them to
public static var allAccountMappings: [String: String] {
storage.dictionary(forKey: accountsKey) as? [String: String] ?? [:]
}
// Date tolerance to check for duplicate transactions when importing
///
/// See also `dateToleranceInDays` which offers this value as Int
public static var dateTolerance: TimeInterval {
Double(dateToleranceInDays * 60 * 60 * 24)
}
/// Date tolerance in days to check for duplicate transactions when importing
///
/// See also `dateTolerance` which offers this value as `TimeInterval`
public static var dateToleranceInDays: Int {
get {
if let daysString = storage.string(forKey: Self.dateToleranceKey), let days = Int(daysString) {
return days
}
return defaultDateTolerance
}
set(newValue) {
// the string conversion is a workaround for https://bugs.swift.org/plugins/servlet/mobile#issue/SR-15124
storage.set("\(newValue)", forKey: dateToleranceKey)
}
}
/// Save a new mapping of a description the user wants to automatically apply to
/// new transactions
///
/// Note: Do not use this function to save the mapping for an imported transaction
/// (use the functions on `ImportedTransaction` instead), but only for adjustments
/// made on a settings screen.
///
/// - Parameters:
/// - key: original description of the imported transaction
/// - description: new description - Use nil to delete a mapping.
public static func setDescriptionMapping(key: String, description: String?) {
var desciptions = storage.dictionary(forKey: descriptionKey) as? [String: String] ?? [:]
desciptions[key] = description
storage.set(desciptions, forKey: descriptionKey)
}
/// Save a new mapping of a payee the user wants to automatically apply to
/// new transactions with a certain description
///
/// Note: Do not use this function to save the mapping for an imported transaction
/// (use the functions on `ImportedTransaction` instead), but only for adjustments
/// made on a settings screen.
///
/// - Parameters:
/// - key: original description of an imported transaction
/// - payee: payee to map transactions with this description to. Use nil to delete a mapping.
public static func setPayeeMapping(key: String, payee: String?) {
var payees = storage.dictionary(forKey: payeesKey) as? [String: String] ?? [:]
payees[key] = payee
storage.set(payees, forKey: payeesKey)
}
/// Save a new mapping of an account the user wants to automatically apply to
/// new transactions from a certain payee
///
/// Note: Do not use this function to save the mapping for an imported transaction
/// (use the functions on `ImportedTransaction` instead), but only for adjustments
/// made on a settings screen.
///
/// - Parameters:
/// - key: payee
/// - account: account name string - Use nil to delete a mapping
public static func setAccountMapping(key: String, account: String?) {
var accounts = storage.dictionary(forKey: accountsKey) as? [String: String] ?? [:]
accounts[key] = account
storage.set(accounts, forKey: accountsKey)
}
}
extension UserDefaults: SettingsStorage {
}