mercury_banking 0.5.37 → 0.6.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/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 -22
- data/lib/mercury_banking/cli/accounts.rb +24 -24
- data/lib/mercury_banking/cli/base.rb +13 -28
- data/lib/mercury_banking/cli/financials.rb +247 -195
- 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 +74 -61
- data/lib/mercury_banking/cli.rb +51 -49
- 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 -0
- data/mercury_banking.gemspec +15 -12
- metadata +39 -38
@@ -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,81 +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
|
-
format = options[:format]
|
31
|
-
|
34
|
+
format = options[:format] || 'all'
|
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"]
|
44
|
+
|
40
45
|
puts "Fetching transactions for #{account_name} (#{account_id})..."
|
41
|
-
|
46
|
+
|
42
47
|
# Get all transactions for this account
|
43
48
|
transactions = client.get_transactions(account_id, start_date)
|
44
|
-
|
49
|
+
|
50
|
+
# Add account information to each transaction
|
51
|
+
transactions.each do |transaction|
|
52
|
+
transaction["accountName"] = account_name
|
53
|
+
transaction["accountId"] = account_id
|
54
|
+
transaction["accountNumber"] = account_number
|
55
|
+
end
|
56
|
+
|
45
57
|
# Filter by end date if specified
|
46
58
|
if end_date
|
47
59
|
end_date_obj = Date.parse(end_date)
|
48
60
|
transactions = transactions.select do |t|
|
49
|
-
transaction_date =
|
61
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
50
62
|
transaction_date <= end_date_obj
|
51
63
|
end
|
52
64
|
end
|
53
|
-
|
65
|
+
|
54
66
|
if transactions.empty?
|
55
67
|
puts "No transactions found for #{account_name}."
|
56
68
|
next
|
57
69
|
end
|
58
|
-
|
70
|
+
|
59
71
|
# Group transactions by month
|
60
72
|
transactions_by_month = {}
|
61
|
-
|
73
|
+
|
62
74
|
transactions.each do |t|
|
63
75
|
# Get the month from the transaction date
|
64
|
-
date =
|
76
|
+
date = Date.parse(t["postedAt"] || t["createdAt"])
|
65
77
|
month_key = "#{date.year}-#{date.month.to_s.rjust(2, '0')}"
|
66
|
-
|
78
|
+
|
67
79
|
# Initialize the month array if it doesn't exist
|
68
80
|
transactions_by_month[month_key] ||= []
|
69
|
-
|
81
|
+
|
70
82
|
# Add the transaction to the month array
|
71
83
|
transactions_by_month[month_key] << t
|
72
84
|
end
|
73
|
-
|
85
|
+
|
74
86
|
# For each month, save transactions to file
|
75
87
|
transactions_by_month.each do |month, month_transactions|
|
76
88
|
# Use the full account number for the filename
|
77
89
|
account_number = account["accountNumber"]
|
78
|
-
|
90
|
+
|
79
91
|
# Create filenames for different formats
|
80
92
|
csv_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.csv")
|
81
93
|
beancount_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.beancount")
|
82
94
|
ledger_filename = File.join(output_dir, "#{month}-Mercury-#{account_number}.ledger")
|
83
|
-
|
95
|
+
|
84
96
|
# Export transactions in the requested format
|
85
97
|
case format
|
86
98
|
when 'csv'
|
@@ -95,20 +107,20 @@ module MercuryBanking
|
|
95
107
|
when 'all'
|
96
108
|
export_to_csv(month_transactions, csv_filename, [], verbose)
|
97
109
|
puts "Exported #{month_transactions.size} transactions to #{csv_filename}"
|
98
|
-
|
110
|
+
|
99
111
|
export_to_beancount(month_transactions, beancount_filename, [], verbose)
|
100
112
|
puts "Exported #{month_transactions.size} transactions to #{beancount_filename}"
|
101
|
-
|
113
|
+
|
102
114
|
export_to_ledger(month_transactions, ledger_filename, [], verbose)
|
103
115
|
puts "Exported #{month_transactions.size} transactions to #{ledger_filename}"
|
104
116
|
end
|
105
117
|
end
|
106
118
|
end
|
107
|
-
|
119
|
+
|
108
120
|
puts "\nTransaction export complete. Files saved to #{output_dir}/ directory."
|
109
121
|
end
|
110
122
|
end
|
111
|
-
|
123
|
+
|
112
124
|
desc "transactions ACCOUNT_ID_OR_NUMBER", "List transactions for an account with their status"
|
113
125
|
method_option :limit, type: :numeric, default: 10, desc: "Number of transactions to show"
|
114
126
|
method_option :start, type: :string, desc: "Start date (YYYY-MM-DD)"
|
@@ -120,70 +132,75 @@ module MercuryBanking
|
|
120
132
|
with_api_client do |client|
|
121
133
|
# Find the account by ID or account number
|
122
134
|
account = find_account(client, account_id_or_number)
|
123
|
-
|
135
|
+
|
124
136
|
if account.nil?
|
125
137
|
puts "Account not found: #{account_id_or_number}"
|
126
138
|
return
|
127
139
|
end
|
128
|
-
|
140
|
+
|
129
141
|
account_id = account["id"]
|
130
|
-
|
142
|
+
|
131
143
|
# Get transactions with optional date filters
|
132
144
|
start_date = options[:start]
|
133
145
|
end_date = options[:end]
|
134
|
-
|
135
|
-
puts "Fetching transactions for #{account[
|
146
|
+
|
147
|
+
puts "Fetching transactions for #{account['name']}..."
|
136
148
|
transactions = client.get_transactions(account_id, start_date)
|
137
|
-
|
149
|
+
|
150
|
+
# Add account information to each transaction
|
151
|
+
transactions.each do |transaction|
|
152
|
+
transaction["accountName"] = account["name"]
|
153
|
+
transaction["accountId"] = account["id"]
|
154
|
+
transaction["accountNumber"] = account["accountNumber"]
|
155
|
+
end
|
156
|
+
|
138
157
|
# Filter by end date if specified
|
139
158
|
if end_date
|
140
159
|
end_date_obj = Date.parse(end_date)
|
141
160
|
transactions = transactions.select do |t|
|
142
|
-
transaction_date =
|
161
|
+
transaction_date = Date.parse(t["postedAt"] || t["createdAt"])
|
143
162
|
transaction_date <= end_date_obj
|
144
163
|
end
|
145
164
|
end
|
146
|
-
|
165
|
+
|
147
166
|
# Filter by status if specified
|
148
|
-
if options[:status]
|
149
|
-
|
150
|
-
end
|
151
|
-
|
167
|
+
transactions = transactions.select { |t| t["status"] == options[:status] } if options[:status]
|
168
|
+
|
152
169
|
# Limit the number of transactions
|
153
170
|
limit = options[:limit]
|
154
|
-
transactions = transactions.take(limit) if limit
|
155
|
-
|
171
|
+
transactions = transactions.take(limit) if limit.positive?
|
172
|
+
|
156
173
|
# Export to CSV if requested
|
157
174
|
if options[:csv]
|
158
175
|
export_to_csv(transactions, options[:csv])
|
159
176
|
puts "Exported #{transactions.size} transactions to #{options[:csv]}"
|
160
177
|
return
|
161
178
|
end
|
162
|
-
|
179
|
+
|
163
180
|
# Output in JSON format if requested
|
164
181
|
if options[:json]
|
165
182
|
puts JSON.pretty_generate(transactions)
|
166
183
|
return
|
167
184
|
end
|
168
|
-
|
185
|
+
|
169
186
|
# Create a table for display
|
170
187
|
table = Terminal::Table.new
|
171
|
-
table.title = "Transactions for #{account[
|
172
|
-
table.headings = [
|
173
|
-
|
188
|
+
table.title = "Transactions for #{account['name']}"
|
189
|
+
table.headings = %w[Date Description Amount Status]
|
190
|
+
|
174
191
|
transactions.each do |t|
|
175
|
-
date =
|
192
|
+
date = Date.parse(t["postedAt"] || t["createdAt"])
|
176
193
|
description = t["bankDescription"] || t["externalMemo"] || "Unknown"
|
177
194
|
amount = t["amount"]
|
178
195
|
status = t["status"]
|
179
|
-
|
196
|
+
|
180
197
|
table.add_row [date, description, "$#{amount}", status]
|
181
198
|
end
|
182
|
-
|
199
|
+
|
183
200
|
puts table
|
184
201
|
end
|
185
202
|
end
|
186
|
-
|
203
|
+
|
187
204
|
# Helper methods that should not be exposed as commands
|
188
205
|
no_commands do
|
189
206
|
# Helper method to sort transactions chronologically
|
@@ -194,24 +211,20 @@ module MercuryBanking
|
|
194
211
|
Time.parse(timestamp)
|
195
212
|
end
|
196
213
|
end
|
197
|
-
|
214
|
+
|
198
215
|
# Helper method to find an account by ID or account number
|
199
216
|
def find_account(client, account_id_or_number)
|
200
217
|
accounts = client.accounts
|
201
|
-
|
218
|
+
|
202
219
|
# Try to find by ID first
|
203
220
|
account = accounts.find { |a| a["id"] == account_id_or_number }
|
204
|
-
|
221
|
+
|
205
222
|
# If not found by ID, try by account number
|
206
|
-
if account.nil?
|
207
|
-
|
208
|
-
end
|
209
|
-
|
223
|
+
account = accounts.find { |a| a["accountNumber"] == account_id_or_number } if account.nil?
|
224
|
+
|
210
225
|
# If still not found, try by the last 4 digits of the account number
|
211
|
-
if account.nil?
|
212
|
-
|
213
|
-
end
|
214
|
-
|
226
|
+
account = accounts.find { |a| a["accountNumber"]&.end_with?(account_id_or_number) } if account.nil?
|
227
|
+
|
215
228
|
account
|
216
229
|
end
|
217
230
|
end
|
@@ -219,4 +232,4 @@ module MercuryBanking
|
|
219
232
|
end
|
220
233
|
end
|
221
234
|
end
|
222
|
-
end
|
235
|
+
end
|