mercury_banking 0.5.38 → 0.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.rubocop.yml +46 -2
- data/CHANGELOG.md +16 -0
- data/Gemfile +13 -12
- data/Gemfile.lock +1 -1
- data/Rakefile +3 -1
- data/bin/console +1 -0
- data/bin/mercury +2 -1
- data/lib/mercury_banking/api.rb +26 -23
- data/lib/mercury_banking/cli/accounts.rb +24 -24
- data/lib/mercury_banking/cli/base.rb +48 -26
- data/lib/mercury_banking/cli/financials.rb +177 -252
- data/lib/mercury_banking/cli/reconciliation.rb +284 -371
- data/lib/mercury_banking/cli/reports.rb +82 -74
- data/lib/mercury_banking/cli/transactions.rb +60 -62
- data/lib/mercury_banking/cli.rb +56 -51
- data/lib/mercury_banking/formatters/export_formatter.rb +99 -97
- data/lib/mercury_banking/formatters/table_formatter.rb +32 -30
- data/lib/mercury_banking/multi.rb +43 -37
- data/lib/mercury_banking/recipient.rb +17 -9
- data/lib/mercury_banking/reconciliation.rb +57 -58
- data/lib/mercury_banking/reports/balance_sheet.rb +210 -218
- data/lib/mercury_banking/reports/reconciliation.rb +114 -100
- data/lib/mercury_banking/utils/command_utils.rb +3 -1
- data/lib/mercury_banking/version.rb +3 -1
- data/lib/mercury_banking.rb +2 -3
- data/mercury_banking.gemspec +15 -12
- metadata +40 -39
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MercuryBanking
|
2
4
|
module CLI
|
3
5
|
# Module for report-related commands
|
@@ -9,11 +11,11 @@ module MercuryBanking
|
|
9
11
|
no_commands do
|
10
12
|
# The balance_sheet method has been moved to the Financials module
|
11
13
|
end
|
12
|
-
|
14
|
+
|
13
15
|
desc 'statement ACCOUNT_NAME', 'Generate a statement for a specific account and period'
|
14
16
|
method_option :start, type: :string, default: '2020-01-01', desc: 'Start date for statement (YYYY-MM-DD)'
|
15
17
|
method_option :end, type: :string, desc: 'End date for statement (YYYY-MM-DD)'
|
16
|
-
method_option :format, type: :string, default: 'text', enum: [
|
18
|
+
method_option :format, type: :string, default: 'text', enum: %w[text json csv], desc: 'Output format'
|
17
19
|
method_option :save, type: :string, desc: 'Save statement to specified file'
|
18
20
|
method_option :debug, type: :boolean, default: false, desc: 'Show debug information about balance calculation'
|
19
21
|
def statement(account_name)
|
@@ -22,117 +24,119 @@ module MercuryBanking
|
|
22
24
|
end_date = options[:end]
|
23
25
|
format = options[:format]
|
24
26
|
debug = options[:debug]
|
25
|
-
|
27
|
+
|
26
28
|
# Find the account by name
|
27
29
|
accounts = client.accounts
|
28
30
|
account = accounts.find { |a| a["name"] == account_name }
|
29
|
-
|
31
|
+
|
30
32
|
unless account
|
31
33
|
puts "Error: Account '#{account_name}' not found. Available accounts:"
|
32
34
|
accounts.each { |a| puts "- #{a['name']}" }
|
33
35
|
return
|
34
36
|
end
|
35
|
-
|
37
|
+
|
36
38
|
# Get transactions for the account
|
37
39
|
transactions = client.get_transactions(account["id"], start_date)
|
38
|
-
|
40
|
+
|
39
41
|
# Filter by end date if specified
|
40
42
|
if end_date
|
41
43
|
end_date_obj = Date.parse(end_date)
|
42
44
|
transactions = transactions.select do |t|
|
43
|
-
transaction_date =
|
45
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
44
46
|
transaction_date <= end_date_obj
|
45
47
|
end
|
46
48
|
end
|
47
|
-
|
49
|
+
|
48
50
|
if transactions.empty?
|
49
51
|
puts "No transactions found for the specified period."
|
50
52
|
return
|
51
53
|
end
|
52
|
-
|
54
|
+
|
53
55
|
# Sort transactions by date
|
54
56
|
transactions = transactions.sort_by do |t|
|
55
57
|
date = t["postedAt"] || t["createdAt"]
|
56
58
|
Time.parse(date)
|
57
59
|
end
|
58
|
-
|
60
|
+
|
59
61
|
# Calculate opening and closing balances
|
60
62
|
current_balance = account["currentBalance"]
|
61
63
|
closing_balance = current_balance
|
62
|
-
|
63
|
-
if debug
|
64
|
-
|
65
|
-
end
|
66
|
-
|
64
|
+
|
65
|
+
puts "Debug: Current balance from Mercury API: $#{format('%.2f', current_balance)}" if debug
|
66
|
+
|
67
67
|
# Subtract all transactions that occurred after the end date
|
68
68
|
if end_date
|
69
69
|
end_date_obj = Date.parse(end_date)
|
70
70
|
after_end_date_transactions = transactions.select do |t|
|
71
|
-
transaction_date =
|
71
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
72
72
|
transaction_date > end_date_obj
|
73
73
|
end
|
74
|
-
|
74
|
+
|
75
75
|
if debug && after_end_date_transactions.any?
|
76
76
|
puts "Debug: Transactions after end date (#{end_date}):"
|
77
77
|
after_end_date_transactions.each do |t|
|
78
78
|
date = t["postedAt"] ? Time.parse(t["postedAt"]).strftime("%Y-%m-%d") : Time.parse(t["createdAt"]).strftime("%Y-%m-%d")
|
79
|
-
puts " #{date}: $#{format(
|
79
|
+
puts " #{date}: $#{format('%.2f', t['amount'])}"
|
80
80
|
end
|
81
81
|
end
|
82
|
-
|
82
|
+
|
83
83
|
after_end_date_sum = after_end_date_transactions.sum { |t| t["amount"] }
|
84
84
|
closing_balance = current_balance - after_end_date_sum
|
85
|
-
|
86
|
-
if debug
|
87
|
-
puts "Debug: Sum of transactions after end date: $#{format("%.2f", after_end_date_sum)}"
|
88
|
-
puts "Debug: Closing balance at end date: $#{format("%.2f", closing_balance)}"
|
89
|
-
end
|
90
|
-
else
|
85
|
+
|
91
86
|
if debug
|
92
|
-
puts "Debug:
|
87
|
+
puts "Debug: Sum of transactions after end date: $#{format('%.2f', after_end_date_sum)}"
|
88
|
+
puts "Debug: Closing balance at end date: $#{format('%.2f', closing_balance)}"
|
93
89
|
end
|
90
|
+
elsif debug
|
91
|
+
puts "Debug: No end date specified, closing balance equals current balance"
|
94
92
|
end
|
95
|
-
|
93
|
+
|
96
94
|
# Calculate opening balance by subtracting all transactions in the period
|
97
95
|
opening_balance = closing_balance
|
98
|
-
|
99
|
-
if debug
|
100
|
-
|
101
|
-
end
|
102
|
-
|
96
|
+
|
97
|
+
puts "Debug: Transactions in the statement period:" if debug
|
98
|
+
|
103
99
|
transactions_sum = 0
|
104
100
|
transactions.each do |t|
|
105
101
|
amount = t["amount"]
|
106
102
|
transactions_sum += amount
|
107
|
-
|
103
|
+
|
108
104
|
if debug
|
109
105
|
date = t["postedAt"] ? Time.parse(t["postedAt"]).strftime("%Y-%m-%d") : Time.parse(t["createdAt"]).strftime("%Y-%m-%d")
|
110
|
-
puts " #{date}: $#{format(
|
106
|
+
puts " #{date}: $#{format('%.2f', amount)}"
|
111
107
|
end
|
112
|
-
|
108
|
+
|
113
109
|
opening_balance -= amount
|
114
110
|
end
|
115
|
-
|
111
|
+
|
116
112
|
if debug
|
117
|
-
puts "Debug: Sum of transactions in period: $#{format(
|
118
|
-
puts "Debug: Opening balance calculation: $#{format(
|
113
|
+
puts "Debug: Sum of transactions in period: $#{format('%.2f', transactions_sum)}"
|
114
|
+
puts "Debug: Opening balance calculation: $#{format('%.2f',
|
115
|
+
closing_balance)} - $#{format('%.2f',
|
116
|
+
transactions_sum)} = $#{format(
|
117
|
+
'%.2f', opening_balance
|
118
|
+
)}"
|
119
119
|
end
|
120
|
-
|
120
|
+
|
121
121
|
# Generate statement based on format
|
122
122
|
case format
|
123
123
|
when 'text'
|
124
|
-
generate_text_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
124
|
+
generate_text_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
125
|
+
options[:save], debug)
|
125
126
|
when 'json'
|
126
|
-
generate_json_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
127
|
+
generate_json_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
128
|
+
options[:save])
|
127
129
|
when 'csv'
|
128
|
-
generate_csv_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
130
|
+
generate_csv_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
131
|
+
options[:save])
|
129
132
|
end
|
130
133
|
end
|
131
134
|
end
|
132
|
-
|
135
|
+
|
133
136
|
private
|
134
|
-
|
135
|
-
def generate_text_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
137
|
+
|
138
|
+
def generate_text_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
139
|
+
save_path, debug = false)
|
136
140
|
# Create statement header
|
137
141
|
statement = []
|
138
142
|
statement << "Mercury Banking Statement"
|
@@ -140,13 +144,13 @@ module MercuryBanking
|
|
140
144
|
statement << "Period: #{start_date} to #{end_date || 'present'}"
|
141
145
|
statement << "Generated on: #{Time.now.strftime('%Y-%m-%d %H:%M:%S')}"
|
142
146
|
statement << ""
|
143
|
-
statement << "Opening Balance: $#{format(
|
147
|
+
statement << "Opening Balance: $#{format('%.2f', opening_balance)}"
|
144
148
|
statement << ""
|
145
149
|
statement << "Transactions:"
|
146
|
-
statement << "-" * 80
|
147
|
-
statement << "Date
|
148
|
-
statement << "-" * 80
|
149
|
-
|
150
|
+
statement << ("-" * 80)
|
151
|
+
statement << ("#{'Date'.ljust(12)}#{'Description'.ljust(40)}#{'Amount'.ljust(15)}Balance")
|
152
|
+
statement << ("-" * 80)
|
153
|
+
|
150
154
|
# Add transactions
|
151
155
|
running_balance = opening_balance
|
152
156
|
transactions.each do |t|
|
@@ -155,13 +159,15 @@ module MercuryBanking
|
|
155
159
|
description = description.length > 37 ? "#{description[0..34]}..." : description
|
156
160
|
amount = t["amount"]
|
157
161
|
running_balance += amount
|
158
|
-
|
159
|
-
statement << date.ljust(12) + description.ljust(40) + format("$%.2f",
|
162
|
+
|
163
|
+
statement << (date.ljust(12) + description.ljust(40) + format("$%.2f",
|
164
|
+
amount).rjust(15) + format("$%.2f",
|
165
|
+
running_balance).rjust(15))
|
160
166
|
end
|
161
|
-
|
162
|
-
statement << "-" * 80
|
163
|
-
statement << "Closing Balance: $#{format(
|
164
|
-
|
167
|
+
|
168
|
+
statement << ("-" * 80)
|
169
|
+
statement << "Closing Balance: $#{format('%.2f', closing_balance)}"
|
170
|
+
|
165
171
|
if debug
|
166
172
|
statement << ""
|
167
173
|
statement << "Debug Information:"
|
@@ -169,7 +175,7 @@ module MercuryBanking
|
|
169
175
|
statement << "- Closing balance is the current balance adjusted for any transactions after the end date"
|
170
176
|
statement << "- Running balance starts with the opening balance and adds each transaction amount"
|
171
177
|
end
|
172
|
-
|
178
|
+
|
173
179
|
# Output or save
|
174
180
|
if save_path
|
175
181
|
File.write(save_path, statement.join("\n"))
|
@@ -178,8 +184,9 @@ module MercuryBanking
|
|
178
184
|
puts statement.join("\n")
|
179
185
|
end
|
180
186
|
end
|
181
|
-
|
182
|
-
def generate_json_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
187
|
+
|
188
|
+
def generate_json_statement(account, transactions, opening_balance, closing_balance, start_date, end_date,
|
189
|
+
save_path)
|
183
190
|
# Format transactions
|
184
191
|
formatted_transactions = transactions.map do |t|
|
185
192
|
{
|
@@ -189,7 +196,7 @@ module MercuryBanking
|
|
189
196
|
status: t["status"]
|
190
197
|
}
|
191
198
|
end
|
192
|
-
|
199
|
+
|
193
200
|
# Create statement object
|
194
201
|
statement = {
|
195
202
|
account: {
|
@@ -208,10 +215,10 @@ module MercuryBanking
|
|
208
215
|
transactions: formatted_transactions,
|
209
216
|
generated_at: Time.now.iso8601
|
210
217
|
}
|
211
|
-
|
218
|
+
|
212
219
|
# Output or save
|
213
220
|
json_output = JSON.pretty_generate(statement)
|
214
|
-
|
221
|
+
|
215
222
|
if save_path
|
216
223
|
File.write(save_path, json_output)
|
217
224
|
puts "Statement saved to #{save_path}"
|
@@ -219,19 +226,20 @@ module MercuryBanking
|
|
219
226
|
puts json_output
|
220
227
|
end
|
221
228
|
end
|
222
|
-
|
223
|
-
def generate_csv_statement(
|
229
|
+
|
230
|
+
def generate_csv_statement(_account, transactions, opening_balance, closing_balance, start_date, end_date,
|
231
|
+
save_path)
|
224
232
|
require 'csv'
|
225
|
-
|
233
|
+
|
226
234
|
# Prepare CSV data
|
227
235
|
csv_data = []
|
228
|
-
|
236
|
+
|
229
237
|
# Add header row
|
230
|
-
csv_data << [
|
231
|
-
|
238
|
+
csv_data << %w[Date Description Amount Balance Status]
|
239
|
+
|
232
240
|
# Add opening balance row
|
233
241
|
csv_data << [start_date, "Opening Balance", "", opening_balance, ""]
|
234
|
-
|
242
|
+
|
235
243
|
# Add transactions
|
236
244
|
running_balance = opening_balance
|
237
245
|
transactions.each do |t|
|
@@ -239,18 +247,18 @@ module MercuryBanking
|
|
239
247
|
description = t["bankDescription"] || t["externalMemo"] || "Unknown transaction"
|
240
248
|
amount = t["amount"]
|
241
249
|
running_balance += amount
|
242
|
-
|
250
|
+
|
243
251
|
csv_data << [date, description, amount, running_balance, t["status"]]
|
244
252
|
end
|
245
|
-
|
253
|
+
|
246
254
|
# Add closing balance row
|
247
255
|
csv_data << [end_date || Time.now.strftime("%Y-%m-%d"), "Closing Balance", "", closing_balance, ""]
|
248
|
-
|
256
|
+
|
249
257
|
# Output or save
|
250
258
|
csv_output = CSV.generate do |csv|
|
251
259
|
csv_data.each { |row| csv << row }
|
252
260
|
end
|
253
|
-
|
261
|
+
|
254
262
|
if save_path
|
255
263
|
File.write(save_path, csv_output)
|
256
264
|
puts "Statement saved to #{save_path}"
|
@@ -262,4 +270,4 @@ module MercuryBanking
|
|
262
270
|
end
|
263
271
|
end
|
264
272
|
end
|
265
|
-
end
|
273
|
+
end
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module MercuryBanking
|
2
4
|
module CLI
|
3
5
|
# Module for transaction-related commands
|
@@ -6,89 +8,91 @@ module MercuryBanking
|
|
6
8
|
def self.included(base)
|
7
9
|
base.class_eval do
|
8
10
|
include MercuryBanking::Formatters::ExportFormatter
|
9
|
-
|
11
|
+
|
10
12
|
desc 'transactions_download', 'Download all Mercury transactions as CSV files'
|
11
13
|
method_option :output_dir, type: :string, default: 'transactions', desc: 'Directory to save transaction files'
|
12
|
-
method_option :start_date, type: :string, default: '2020-01-01',
|
14
|
+
method_option :start_date, type: :string, default: '2020-01-01',
|
15
|
+
desc: 'Start date for transactions (YYYY-MM-DD)'
|
13
16
|
method_option :end_date, type: :string, desc: 'End date for transactions (YYYY-MM-DD)'
|
14
|
-
method_option :format, type: :string, default: 'csv', enum: [
|
17
|
+
method_option :format, type: :string, default: 'csv', enum: %w[csv beancount ledger all],
|
18
|
+
desc: 'Output format (csv, beancount, ledger, or all)'
|
15
19
|
method_option :verbose, type: :boolean, default: false, desc: 'Show detailed debug information'
|
16
20
|
def transactions_download
|
17
21
|
with_api_client do |client|
|
18
22
|
# Create output directory if it doesn't exist
|
19
23
|
output_dir = options[:output_dir]
|
20
24
|
FileUtils.mkdir_p(output_dir)
|
21
|
-
|
25
|
+
|
22
26
|
# Get all accounts
|
23
27
|
accounts = client.accounts
|
24
|
-
|
28
|
+
|
25
29
|
# Get start and end dates
|
26
30
|
start_date = options[:start_date]
|
27
31
|
end_date = options[:end_date]
|
28
|
-
|
32
|
+
|
29
33
|
# Get format
|
30
34
|
format = options[:format] || 'all'
|
31
|
-
|
35
|
+
|
32
36
|
# Get verbose option
|
33
37
|
verbose = options[:verbose]
|
34
|
-
|
38
|
+
|
35
39
|
# For each account, get transactions and save to file
|
36
40
|
accounts.each do |account|
|
37
41
|
account_id = account["id"]
|
38
42
|
account_name = account["name"]
|
39
43
|
account_number = account["accountNumber"]
|
40
|
-
|
44
|
+
|
41
45
|
puts "Fetching transactions for #{account_name} (#{account_id})..."
|
42
|
-
|
46
|
+
|
43
47
|
# Get all transactions for this account
|
44
48
|
transactions = client.get_transactions(account_id, start_date)
|
45
|
-
|
49
|
+
|
46
50
|
# Add account information to each transaction
|
47
51
|
transactions.each do |transaction|
|
48
52
|
transaction["accountName"] = account_name
|
49
53
|
transaction["accountId"] = account_id
|
50
54
|
transaction["accountNumber"] = account_number
|
51
55
|
end
|
52
|
-
|
56
|
+
|
53
57
|
# Filter by end date if specified
|
54
58
|
if end_date
|
55
59
|
end_date_obj = Date.parse(end_date)
|
56
60
|
transactions = transactions.select do |t|
|
57
|
-
transaction_date =
|
61
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
58
62
|
transaction_date <= end_date_obj
|
59
63
|
end
|
60
64
|
end
|
61
|
-
|
65
|
+
|
62
66
|
if transactions.empty?
|
63
67
|
puts "No transactions found for #{account_name}."
|
64
68
|
next
|
65
69
|
end
|
66
|
-
|
70
|
+
|
67
71
|
# Group transactions by month
|
68
72
|
transactions_by_month = {}
|
69
|
-
|
73
|
+
|
70
74
|
transactions.each do |t|
|
71
75
|
# Get the month from the transaction date
|
72
|
-
date =
|
76
|
+
date = Date.parse(t["postedAt"] || t["createdAt"])
|
73
77
|
month_key = "#{date.year}-#{date.month.to_s.rjust(2, '0')}"
|
74
|
-
|
78
|
+
|
75
79
|
# Initialize the month array if it doesn't exist
|
76
80
|
transactions_by_month[month_key] ||= []
|
77
|
-
|
81
|
+
|
78
82
|
# Add the transaction to the month array
|
79
83
|
transactions_by_month[month_key] << t
|
80
84
|
end
|
81
|
-
|
85
|
+
|
82
86
|
# For each month, save transactions to file
|
83
87
|
transactions_by_month.each do |month, month_transactions|
|
84
88
|
# Use the full account number for the filename
|
85
89
|
account_number = account["accountNumber"]
|
86
|
-
|
90
|
+
|
87
91
|
# Create filenames for different formats
|
88
92
|
csv_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.csv")
|
89
93
|
beancount_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.beancount")
|
90
94
|
ledger_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.ledger")
|
91
|
-
|
95
|
+
|
92
96
|
# Export transactions in the requested format
|
93
97
|
case format
|
94
98
|
when 'csv'
|
@@ -103,20 +107,20 @@ module MercuryBanking
|
|
103
107
|
when 'all'
|
104
108
|
export_to_csv(month_transactions, csv_filename, [], verbose)
|
105
109
|
puts "Exported #{month_transactions.size} transactions to #{csv_filename}"
|
106
|
-
|
110
|
+
|
107
111
|
export_to_beancount(month_transactions, beancount_filename, [], verbose)
|
108
112
|
puts "Exported #{month_transactions.size} transactions to #{beancount_filename}"
|
109
|
-
|
113
|
+
|
110
114
|
export_to_ledger(month_transactions, ledger_filename, [], verbose)
|
111
115
|
puts "Exported #{month_transactions.size} transactions to #{ledger_filename}"
|
112
116
|
end
|
113
117
|
end
|
114
118
|
end
|
115
|
-
|
119
|
+
|
116
120
|
puts "\nTransaction export complete. Files saved to #{output_dir}/ directory."
|
117
121
|
end
|
118
122
|
end
|
119
|
-
|
123
|
+
|
120
124
|
desc "transactions ACCOUNT_ID_OR_NUMBER", "List transactions for an account with their status"
|
121
125
|
method_option :limit, type: :numeric, default: 10, desc: "Number of transactions to show"
|
122
126
|
method_option :start, type: :string, desc: "Start date (YYYY-MM-DD)"
|
@@ -128,77 +132,75 @@ module MercuryBanking
|
|
128
132
|
with_api_client do |client|
|
129
133
|
# Find the account by ID or account number
|
130
134
|
account = find_account(client, account_id_or_number)
|
131
|
-
|
135
|
+
|
132
136
|
if account.nil?
|
133
137
|
puts "Account not found: #{account_id_or_number}"
|
134
138
|
return
|
135
139
|
end
|
136
|
-
|
140
|
+
|
137
141
|
account_id = account["id"]
|
138
|
-
|
142
|
+
|
139
143
|
# Get transactions with optional date filters
|
140
144
|
start_date = options[:start]
|
141
145
|
end_date = options[:end]
|
142
|
-
|
143
|
-
puts "Fetching transactions for #{account[
|
146
|
+
|
147
|
+
puts "Fetching transactions for #{account['name']}..."
|
144
148
|
transactions = client.get_transactions(account_id, start_date)
|
145
|
-
|
149
|
+
|
146
150
|
# Add account information to each transaction
|
147
151
|
transactions.each do |transaction|
|
148
152
|
transaction["accountName"] = account["name"]
|
149
153
|
transaction["accountId"] = account["id"]
|
150
154
|
transaction["accountNumber"] = account["accountNumber"]
|
151
155
|
end
|
152
|
-
|
156
|
+
|
153
157
|
# Filter by end date if specified
|
154
158
|
if end_date
|
155
159
|
end_date_obj = Date.parse(end_date)
|
156
160
|
transactions = transactions.select do |t|
|
157
|
-
transaction_date =
|
161
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
158
162
|
transaction_date <= end_date_obj
|
159
163
|
end
|
160
164
|
end
|
161
|
-
|
165
|
+
|
162
166
|
# Filter by status if specified
|
163
|
-
if options[:status]
|
164
|
-
|
165
|
-
end
|
166
|
-
|
167
|
+
transactions = transactions.select { |t| t["status"] == options[:status] } if options[:status]
|
168
|
+
|
167
169
|
# Limit the number of transactions
|
168
170
|
limit = options[:limit]
|
169
|
-
transactions = transactions.take(limit) if limit
|
170
|
-
|
171
|
+
transactions = transactions.take(limit) if limit.positive?
|
172
|
+
|
171
173
|
# Export to CSV if requested
|
172
174
|
if options[:csv]
|
173
175
|
export_to_csv(transactions, options[:csv])
|
174
176
|
puts "Exported #{transactions.size} transactions to #{options[:csv]}"
|
175
177
|
return
|
176
178
|
end
|
177
|
-
|
179
|
+
|
178
180
|
# Output in JSON format if requested
|
179
181
|
if options[:json]
|
180
182
|
puts JSON.pretty_generate(transactions)
|
181
183
|
return
|
182
184
|
end
|
183
|
-
|
185
|
+
|
184
186
|
# Create a table for display
|
185
187
|
table = Terminal::Table.new
|
186
|
-
table.title = "Transactions for #{account[
|
187
|
-
table.headings = [
|
188
|
-
|
188
|
+
table.title = "Transactions for #{account['name']}"
|
189
|
+
table.headings = %w[Date Description Amount Status]
|
190
|
+
|
189
191
|
transactions.each do |t|
|
190
|
-
date =
|
192
|
+
date = Date.parse(t["postedAt"] || t["createdAt"])
|
191
193
|
description = t["bankDescription"] || t["externalMemo"] || "Unknown"
|
192
194
|
amount = t["amount"]
|
193
195
|
status = t["status"]
|
194
|
-
|
196
|
+
|
195
197
|
table.add_row [date, description, "$#{amount}", status]
|
196
198
|
end
|
197
|
-
|
199
|
+
|
198
200
|
puts table
|
199
201
|
end
|
200
202
|
end
|
201
|
-
|
203
|
+
|
202
204
|
# Helper methods that should not be exposed as commands
|
203
205
|
no_commands do
|
204
206
|
# Helper method to sort transactions chronologically
|
@@ -209,24 +211,20 @@ module MercuryBanking
|
|
209
211
|
Time.parse(timestamp)
|
210
212
|
end
|
211
213
|
end
|
212
|
-
|
214
|
+
|
213
215
|
# Helper method to find an account by ID or account number
|
214
216
|
def find_account(client, account_id_or_number)
|
215
217
|
accounts = client.accounts
|
216
|
-
|
218
|
+
|
217
219
|
# Try to find by ID first
|
218
220
|
account = accounts.find { |a| a["id"] == account_id_or_number }
|
219
|
-
|
221
|
+
|
220
222
|
# If not found by ID, try by account number
|
221
|
-
if account.nil?
|
222
|
-
|
223
|
-
end
|
224
|
-
|
223
|
+
account = accounts.find { |a| a["accountNumber"] == account_id_or_number } if account.nil?
|
224
|
+
|
225
225
|
# If still not found, try by the last 4 digits of the account number
|
226
|
-
if account.nil?
|
227
|
-
|
228
|
-
end
|
229
|
-
|
226
|
+
account = accounts.find { |a| a["accountNumber"]&.end_with?(account_id_or_number) } if account.nil?
|
227
|
+
|
230
228
|
account
|
231
229
|
end
|
232
230
|
end
|
@@ -234,4 +232,4 @@ module MercuryBanking
|
|
234
232
|
end
|
235
233
|
end
|
236
234
|
end
|
237
|
-
end
|
235
|
+
end
|