lunchmoney 1.4.1 → 1.5.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/.github/workflows/build_and_publish_yard_docs.yml +2 -2
- data/.github/workflows/ci.yml +9 -10
- data/.github/workflows/rbi-updater.yml +1 -1
- data/.github/workflows/release_pipeline.yml +1 -1
- data/.rubocop.yml +1 -1
- data/.ruby-version +1 -1
- data/.toys/.toys.rb +8 -0
- data/Gemfile +1 -1
- data/Gemfile.lock +76 -60
- data/README.md +0 -2
- data/SECURITY.md +151 -0
- data/bin/check_vcr_version +94 -0
- data/lib/lunchmoney/api.rb +25 -38
- data/lib/lunchmoney/calls/assets.rb +10 -13
- data/lib/lunchmoney/calls/base.rb +59 -7
- data/lib/lunchmoney/calls/budgets.rb +22 -25
- data/lib/lunchmoney/calls/categories.rb +28 -36
- data/lib/lunchmoney/calls/crypto.rb +7 -9
- data/lib/lunchmoney/calls/plaid_accounts.rb +7 -9
- data/lib/lunchmoney/calls/recurring_expenses.rb +4 -5
- data/lib/lunchmoney/calls/tags.rb +3 -4
- data/lib/lunchmoney/calls/transactions.rb +28 -36
- data/lib/lunchmoney/calls/users.rb +3 -4
- data/lib/lunchmoney/configuration.rb +20 -0
- data/lib/lunchmoney/objects/object.rb +4 -9
- data/lib/lunchmoney/validators.rb +8 -6
- data/lib/lunchmoney/version.rb +1 -1
- data/lib/lunchmoney.rb +3 -3
- data/lunchmoney.gemspec +1 -1
- data/sorbet/rbi/annotations/activesupport.rbi +35 -0
- data/sorbet/rbi/dsl/active_support/callbacks.rbi +0 -2
- data/sorbet/rbi/gems/{activesupport@7.2.2.1.rbi → activesupport@8.0.2.1.rbi} +1369 -989
- data/sorbet/rbi/gems/{ast@2.4.2.rbi → ast@2.4.3.rbi} +4 -3
- data/sorbet/rbi/gems/{base64@0.2.0.rbi → base64@0.3.0.rbi} +76 -39
- data/sorbet/rbi/gems/{benchmark@0.4.0.rbi → benchmark@0.4.1.rbi} +50 -49
- data/sorbet/rbi/gems/bigdecimal@3.2.2.rbi +275 -0
- data/sorbet/rbi/gems/{dotenv@3.1.7.rbi → dotenv@3.1.8.rbi} +9 -9
- data/sorbet/rbi/gems/{drb@2.2.1.rbi → drb@2.2.3.rbi} +503 -188
- data/sorbet/rbi/gems/{faraday-net_http@3.4.0.rbi → faraday-net_http@3.4.1.rbi} +23 -23
- data/sorbet/rbi/gems/{faraday@2.12.2.rbi → faraday@2.13.4.rbi} +468 -141
- data/sorbet/rbi/gems/{hashdiff@1.1.2.rbi → hashdiff@1.2.0.rbi} +5 -3
- data/sorbet/rbi/gems/{json@2.10.2.rbi → json@2.13.2.rbi} +386 -175
- data/sorbet/rbi/gems/{kramdown@2.4.0.rbi → kramdown@2.5.1.rbi} +316 -234
- data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
- data/sorbet/rbi/gems/{logger@1.6.6.rbi → logger@1.7.0.rbi} +63 -40
- data/sorbet/rbi/gems/{parser@3.3.7.1.rbi → parser@3.3.9.0.rbi} +303 -291
- data/sorbet/rbi/gems/{rack@3.1.9.rbi → rack@3.2.1.rbi} +712 -547
- data/sorbet/rbi/gems/{rake@13.2.1.rbi → rake@13.3.0.rbi} +238 -227
- data/sorbet/rbi/gems/{rbi@0.3.1.rbi → rbi@0.3.6.rbi} +1084 -2521
- data/sorbet/rbi/gems/{rbs@3.9.0.rbi → rbs@4.0.0.dev.4.rbi} +1336 -419
- data/sorbet/rbi/gems/{regexp_parser@2.10.0.rbi → regexp_parser@2.11.2.rbi} +1044 -956
- data/sorbet/rbi/gems/require-hooks@0.2.2.rbi +110 -0
- data/sorbet/rbi/gems/{rexml@3.4.1.rbi → rexml@3.4.2.rbi} +302 -292
- data/sorbet/rbi/gems/{rubocop-ast@1.38.0.rbi → rubocop-ast@1.46.0.rbi} +802 -1016
- data/sorbet/rbi/gems/{rubocop-minitest@0.36.0.rbi → rubocop-minitest@0.38.2.rbi} +129 -93
- data/sorbet/rbi/gems/{rubocop-rails@2.29.1.rbi → rubocop-rails@2.33.3.rbi} +575 -230
- data/sorbet/rbi/gems/{rubocop-shopify@2.15.1.rbi → rubocop-shopify@2.17.1.rbi} +1 -0
- data/sorbet/rbi/gems/{rubocop-sorbet@0.8.7.rbi → rubocop-sorbet@0.10.5.rbi} +761 -83
- data/sorbet/rbi/gems/{rubocop@1.71.2.rbi → rubocop@1.80.1.rbi} +6543 -3097
- data/sorbet/rbi/gems/{spoom@1.6.1.rbi → spoom@1.7.6.rbi} +1179 -2621
- data/sorbet/rbi/gems/{tapioca@0.16.11.rbi → tapioca@0.17.7.rbi} +623 -745
- data/sorbet/rbi/gems/{thor@1.3.2.rbi → thor@1.4.0.rbi} +88 -67
- data/sorbet/rbi/gems/{unicode-display_width@3.1.4.rbi → unicode-display_width@3.1.5.rbi} +5 -5
- data/sorbet/rbi/gems/{vcr@6.3.1.rbi → vcr@6.3.1-ce35c236fe48899f02ddf780973b44cdb756c0ee.rbi} +140 -123
- metadata +42 -38
- data/sorbet/rbi/gems/bigdecimal@3.1.9.rbi +0 -78
- /data/sorbet/rbi/gems/{connection_pool@2.5.0.rbi → connection_pool@2.5.3.rbi} +0 -0
- /data/sorbet/rbi/gems/{language_server-protocol@3.17.0.4.rbi → language_server-protocol@3.17.0.5.rbi} +0 -0
- /data/sorbet/rbi/gems/{parallel@1.26.3.rbi → parallel@1.27.0.rbi} +0 -0
data/lib/lunchmoney/api.rb
CHANGED
@@ -30,7 +30,7 @@ module LunchMoney
|
|
30
30
|
|
31
31
|
sig { params(api_key: T.nilable(String)).void }
|
32
32
|
def initialize(api_key: nil)
|
33
|
-
@api_key = T.let(
|
33
|
+
@api_key = T.let(api_key || LunchMoney.configuration.api_key, T.nilable(String))
|
34
34
|
end
|
35
35
|
|
36
36
|
delegate :me, to: :user_calls
|
@@ -41,9 +41,7 @@ module LunchMoney
|
|
41
41
|
# api.me
|
42
42
|
sig { returns(LunchMoney::Calls::Base) }
|
43
43
|
def user_calls
|
44
|
-
|
45
|
-
@user_calls ||= T.let(LunchMoney::Calls::Users.new(api_key:), T.nilable(LunchMoney::Calls::Users))
|
46
|
-
end
|
44
|
+
memoized_call_instance(:@user_calls, LunchMoney::Calls::Users)
|
47
45
|
end
|
48
46
|
|
49
47
|
delegate :categories,
|
@@ -84,9 +82,7 @@ module LunchMoney
|
|
84
82
|
# api.force_delete_category(1234567)
|
85
83
|
sig { returns(LunchMoney::Calls::Base) }
|
86
84
|
def category_calls
|
87
|
-
|
88
|
-
@category_calls ||= T.let(LunchMoney::Calls::Categories.new(api_key:), T.nilable(LunchMoney::Calls::Categories))
|
89
|
-
end
|
85
|
+
memoized_call_instance(:@category_calls, LunchMoney::Calls::Categories)
|
90
86
|
end
|
91
87
|
|
92
88
|
delegate :tags, to: :tag_calls
|
@@ -97,9 +93,7 @@ module LunchMoney
|
|
97
93
|
# api.tags
|
98
94
|
sig { returns(LunchMoney::Calls::Base) }
|
99
95
|
def tag_calls
|
100
|
-
|
101
|
-
@tag_calls ||= T.let(LunchMoney::Calls::Tags.new(api_key:), T.nilable(LunchMoney::Calls::Tags))
|
102
|
-
end
|
96
|
+
memoized_call_instance(:@tag_calls, LunchMoney::Calls::Tags)
|
103
97
|
end
|
104
98
|
|
105
99
|
delegate :transactions,
|
@@ -160,12 +154,7 @@ module LunchMoney
|
|
160
154
|
# api.delete_transaction_group(905483362)
|
161
155
|
sig { returns(LunchMoney::Calls::Base) }
|
162
156
|
def transaction_calls
|
163
|
-
|
164
|
-
@transaction_calls ||= T.let(
|
165
|
-
LunchMoney::Calls::Transactions.new(api_key:),
|
166
|
-
T.nilable(LunchMoney::Calls::Transactions),
|
167
|
-
)
|
168
|
-
end
|
157
|
+
memoized_call_instance(:@transaction_calls, LunchMoney::Calls::Transactions)
|
169
158
|
end
|
170
159
|
|
171
160
|
delegate :recurring_expenses, to: :recurring_expense_calls
|
@@ -176,12 +165,7 @@ module LunchMoney
|
|
176
165
|
# api.recurring_expenses
|
177
166
|
sig { returns(LunchMoney::Calls::Base) }
|
178
167
|
def recurring_expense_calls
|
179
|
-
|
180
|
-
@recurring_expense_calls ||= T.let(
|
181
|
-
LunchMoney::Calls::RecurringExpenses.new(api_key:),
|
182
|
-
T.nilable(LunchMoney::Calls::RecurringExpenses),
|
183
|
-
)
|
184
|
-
end
|
168
|
+
memoized_call_instance(:@recurring_expense_calls, LunchMoney::Calls::RecurringExpenses)
|
185
169
|
end
|
186
170
|
|
187
171
|
delegate :budgets, :upsert_budget, :remove_budget, to: :budget_calls
|
@@ -193,14 +177,12 @@ module LunchMoney
|
|
193
177
|
# @example [Upsert Budget](https://lunchmoney.dev/#upsert-budget)
|
194
178
|
# api = LunchMoney::Api.new
|
195
179
|
# api.upsert_budget(start_date: "2023-01-01", category_id: 777052, amount: 400.99)
|
196
|
-
# @example [Remove Budget(https://lunchmoney.dev/#remove-budget)
|
180
|
+
# @example [Remove Budget](https://lunchmoney.dev/#remove-budget)
|
197
181
|
# api = LunchMoney::Api.new
|
198
182
|
# api.remove_budget(start_date: "2023-01-01", category_id: 777052)
|
199
183
|
sig { returns(LunchMoney::Calls::Base) }
|
200
184
|
def budget_calls
|
201
|
-
|
202
|
-
@budget_calls ||= T.let(LunchMoney::Calls::Budgets.new(api_key:), T.nilable(LunchMoney::Calls::Budgets))
|
203
|
-
end
|
185
|
+
memoized_call_instance(:@budget_calls, LunchMoney::Calls::Budgets)
|
204
186
|
end
|
205
187
|
|
206
188
|
delegate :assets, :create_asset, :update_asset, to: :asset_calls
|
@@ -221,9 +203,7 @@ module LunchMoney
|
|
221
203
|
# api.update_asset(93746, balance: "99.99")
|
222
204
|
sig { returns(LunchMoney::Calls::Base) }
|
223
205
|
def asset_calls
|
224
|
-
|
225
|
-
@asset_calls ||= T.let(LunchMoney::Calls::Assets.new(api_key:), T.nilable(LunchMoney::Calls::Assets))
|
226
|
-
end
|
206
|
+
memoized_call_instance(:@asset_calls, LunchMoney::Calls::Assets)
|
227
207
|
end
|
228
208
|
|
229
209
|
delegate :plaid_accounts, :plaid_accounts_fetch, to: :plaid_account_calls
|
@@ -237,12 +217,7 @@ module LunchMoney
|
|
237
217
|
# api.plaid_accounts_fetch
|
238
218
|
sig { returns(LunchMoney::Calls::Base) }
|
239
219
|
def plaid_account_calls
|
240
|
-
|
241
|
-
@plaid_account_calls ||= T.let(
|
242
|
-
LunchMoney::Calls::PlaidAccounts.new(api_key:),
|
243
|
-
T.nilable(LunchMoney::Calls::PlaidAccounts),
|
244
|
-
)
|
245
|
-
end
|
220
|
+
memoized_call_instance(:@plaid_account_calls, LunchMoney::Calls::PlaidAccounts)
|
246
221
|
end
|
247
222
|
|
248
223
|
delegate :crypto, :update_crypto, to: :crypto_calls
|
@@ -256,9 +231,7 @@ module LunchMoney
|
|
256
231
|
# api.update_crypto(1234567, name: "New Crypto Name")
|
257
232
|
sig { returns(LunchMoney::Calls::Base) }
|
258
233
|
def crypto_calls
|
259
|
-
|
260
|
-
@crypto_calls ||= T.let(LunchMoney::Calls::Crypto.new(api_key:), T.nilable(LunchMoney::Calls::Crypto))
|
261
|
-
end
|
234
|
+
memoized_call_instance(:@crypto_calls, LunchMoney::Calls::Crypto)
|
262
235
|
end
|
263
236
|
|
264
237
|
private
|
@@ -269,5 +242,19 @@ module LunchMoney
|
|
269
242
|
|
270
243
|
yield
|
271
244
|
end
|
245
|
+
|
246
|
+
sig do
|
247
|
+
type_parameters(:T)
|
248
|
+
.params(
|
249
|
+
ivar_name: Symbol,
|
250
|
+
klass: T.class_of(LunchMoney::Calls::Base),
|
251
|
+
)
|
252
|
+
.returns(LunchMoney::Calls::Base)
|
253
|
+
end
|
254
|
+
def memoized_call_instance(ivar_name, klass)
|
255
|
+
with_valid_api_key do
|
256
|
+
instance_variable_get(ivar_name) || instance_variable_set(ivar_name, klass.new(api_key:))
|
257
|
+
end
|
258
|
+
end
|
272
259
|
end
|
273
260
|
end
|
@@ -11,11 +11,10 @@ module LunchMoney
|
|
11
11
|
def assets
|
12
12
|
response = get("assets")
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
LunchMoney::Objects::Asset.new(**asset)
|
14
|
+
handle_api_response(response) do |body|
|
15
|
+
body[:assets].map do |asset|
|
16
|
+
LunchMoney::Objects::Asset.new(**asset)
|
17
|
+
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
@@ -50,10 +49,9 @@ module LunchMoney
|
|
50
49
|
|
51
50
|
response = post("assets", params)
|
52
51
|
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
LunchMoney::Objects::Asset.new(**response.body)
|
52
|
+
handle_api_response(response) do |body|
|
53
|
+
LunchMoney::Objects::Asset.new(**body)
|
54
|
+
end
|
57
55
|
end
|
58
56
|
|
59
57
|
sig do
|
@@ -88,10 +86,9 @@ module LunchMoney
|
|
88
86
|
|
89
87
|
response = put("assets/#{asset_id}", params)
|
90
88
|
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
LunchMoney::Objects::Asset.new(**response.body)
|
89
|
+
handle_api_response(response) do |body|
|
90
|
+
LunchMoney::Objects::Asset.new(**body)
|
91
|
+
end
|
95
92
|
end
|
96
93
|
end
|
97
94
|
end
|
@@ -22,14 +22,15 @@ module LunchMoney
|
|
22
22
|
|
23
23
|
sig { params(api_key: T.nilable(String)).void }
|
24
24
|
def initialize(api_key: nil)
|
25
|
-
@api_key = T.let(
|
25
|
+
@api_key = T.let(api_key || LunchMoney.configuration.api_key, T.nilable(String))
|
26
|
+
@connections = T.let({}, T::Hash[Symbol, Faraday::Connection])
|
26
27
|
end
|
27
28
|
|
28
29
|
private
|
29
30
|
|
30
31
|
sig { params(endpoint: String, query_params: T.nilable(T::Hash[Symbol, T.untyped])).returns(Faraday::Response) }
|
31
32
|
def get(endpoint, query_params: nil)
|
32
|
-
connection =
|
33
|
+
connection = connection_for(:flat_params)
|
33
34
|
|
34
35
|
if query_params.present?
|
35
36
|
connection.get(BASE_URL + endpoint, query_params)
|
@@ -40,19 +41,19 @@ module LunchMoney
|
|
40
41
|
|
41
42
|
sig { params(endpoint: String, params: T.nilable(T::Hash[Symbol, T.untyped])).returns(Faraday::Response) }
|
42
43
|
def post(endpoint, params)
|
43
|
-
|
44
|
+
connection_for(:json).post(BASE_URL + endpoint, params)
|
44
45
|
end
|
45
46
|
|
46
47
|
sig { params(endpoint: String, body: T::Hash[Symbol, T.untyped]).returns(Faraday::Response) }
|
47
48
|
def put(endpoint, body)
|
48
|
-
|
49
|
+
connection_for(:json).put(BASE_URL + endpoint) do |req|
|
49
50
|
req.body = body
|
50
51
|
end
|
51
52
|
end
|
52
53
|
|
53
54
|
sig { params(endpoint: String, query_params: T.nilable(T::Hash[Symbol, T.untyped])).returns(Faraday::Response) }
|
54
55
|
def delete(endpoint, query_params: nil)
|
55
|
-
connection =
|
56
|
+
connection = connection_for(:flat_params)
|
56
57
|
|
57
58
|
if query_params.present?
|
58
59
|
connection.delete(BASE_URL + endpoint, query_params)
|
@@ -61,12 +62,24 @@ module LunchMoney
|
|
61
62
|
end
|
62
63
|
end
|
63
64
|
|
65
|
+
sig { params(connection_type: Symbol).returns(Faraday::Connection) }
|
66
|
+
def connection_for(connection_type)
|
67
|
+
@connections[connection_type] ||= case connection_type
|
68
|
+
when :json
|
69
|
+
build_connection(json_request: true)
|
70
|
+
when :flat_params
|
71
|
+
build_connection(flat_params: true)
|
72
|
+
else
|
73
|
+
build_connection
|
74
|
+
end
|
75
|
+
end
|
76
|
+
|
64
77
|
sig { params(json_request: T::Boolean, flat_params: T::Boolean).returns(Faraday::Connection) }
|
65
|
-
def
|
78
|
+
def build_connection(json_request: false, flat_params: false)
|
66
79
|
Faraday.new do |conn|
|
67
80
|
conn.request(:authorization, "Bearer", @api_key)
|
68
81
|
conn.request(:json) if json_request
|
69
|
-
|
82
|
+
conn.options.params_encoder = Faraday::FlatParamsEncoder if flat_params
|
70
83
|
conn.response(:json, content_type: /json$/, parser_options: { symbolize_names: true })
|
71
84
|
end
|
72
85
|
end
|
@@ -113,6 +126,45 @@ module LunchMoney
|
|
113
126
|
def clean_params(params)
|
114
127
|
params.reject! { |_key, value| value.nil? }
|
115
128
|
end
|
129
|
+
|
130
|
+
sig do
|
131
|
+
type_parameters(:T)
|
132
|
+
.params(
|
133
|
+
response: Faraday::Response,
|
134
|
+
block: T.proc.params(body: T.untyped).returns(T.type_parameter(:T)),
|
135
|
+
)
|
136
|
+
.returns(T.any(T.type_parameter(:T), LunchMoney::Errors))
|
137
|
+
end
|
138
|
+
def handle_api_response(response, &block)
|
139
|
+
api_errors = errors(response)
|
140
|
+
return api_errors if api_errors.present?
|
141
|
+
|
142
|
+
yield(response.body)
|
143
|
+
end
|
144
|
+
|
145
|
+
sig do
|
146
|
+
type_parameters(:T)
|
147
|
+
.params(
|
148
|
+
response: Faraday::Response,
|
149
|
+
collection_key: Symbol,
|
150
|
+
lazy: T::Boolean,
|
151
|
+
block: T.proc.params(item: T.untyped).returns(T.type_parameter(:T)),
|
152
|
+
)
|
153
|
+
.returns(T.any(T::Enumerable[T.type_parameter(:T)], T::Array[T.type_parameter(:T)], LunchMoney::Errors))
|
154
|
+
end
|
155
|
+
def handle_collection_response(response, collection_key, lazy: false, &block)
|
156
|
+
api_errors = errors(response)
|
157
|
+
return api_errors if api_errors.present?
|
158
|
+
|
159
|
+
collection = response.body[collection_key]
|
160
|
+
return [] unless collection
|
161
|
+
|
162
|
+
if lazy
|
163
|
+
collection.lazy.map(&block)
|
164
|
+
else
|
165
|
+
collection.map(&block)
|
166
|
+
end
|
167
|
+
end
|
116
168
|
end
|
117
169
|
end
|
118
170
|
end
|
@@ -18,29 +18,28 @@ module LunchMoney
|
|
18
18
|
params = clean_params({ start_date:, end_date:, currency: })
|
19
19
|
response = get("budgets", query_params: params)
|
20
20
|
|
21
|
-
|
22
|
-
|
21
|
+
handle_api_response(response) do |body|
|
22
|
+
body.map do |budget|
|
23
|
+
if budget[:data]
|
24
|
+
data_keys = budget[:data].keys
|
25
|
+
data_keys.each do |data_key|
|
26
|
+
budget[:data][data_key] = LunchMoney::Objects::Data.new(**budget[:data][data_key])
|
27
|
+
end
|
28
|
+
end
|
23
29
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
30
|
+
if budget[:config]
|
31
|
+
config_keys = budget[:config].keys
|
32
|
+
config_keys.each do |config_key|
|
33
|
+
budget[:config][config_key] = LunchMoney::Objects::Data.new(**budget[:config][config_key])
|
34
|
+
end
|
29
35
|
end
|
30
|
-
end
|
31
36
|
|
32
|
-
|
33
|
-
|
34
|
-
config_keys.each do |config_key|
|
35
|
-
budget[:config][config_key] = LunchMoney::Objects::Data.new(**budget[:config][config_key])
|
37
|
+
if budget[:recurring]
|
38
|
+
budget[:recurring][:list]&.map! { |recurring| LunchMoney::Objects::RecurringExpenseBase.new(**recurring) }
|
36
39
|
end
|
37
|
-
end
|
38
40
|
|
39
|
-
|
40
|
-
budget[:recurring][:list]&.map! { |recurring| LunchMoney::Objects::RecurringExpenseBase.new(**recurring) }
|
41
|
+
LunchMoney::Objects::Budget.new(**budget)
|
41
42
|
end
|
42
|
-
|
43
|
-
LunchMoney::Objects::Budget.new(**budget)
|
44
43
|
end
|
45
44
|
end
|
46
45
|
|
@@ -59,10 +58,9 @@ module LunchMoney
|
|
59
58
|
params = clean_params({ start_date:, category_id:, amount:, currency: })
|
60
59
|
response = put("budgets", params)
|
61
60
|
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
response.body
|
61
|
+
handle_api_response(response) do |body|
|
62
|
+
body
|
63
|
+
end
|
66
64
|
end
|
67
65
|
|
68
66
|
sig { params(start_date: String, category_id: Integer).returns(T.any(T::Boolean, LunchMoney::Errors)) }
|
@@ -74,10 +72,9 @@ module LunchMoney
|
|
74
72
|
|
75
73
|
response = delete("budgets", query_params: params)
|
76
74
|
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
response.body
|
75
|
+
handle_api_response(response) do |body|
|
76
|
+
body
|
77
|
+
end
|
81
78
|
end
|
82
79
|
end
|
83
80
|
end
|
@@ -7,7 +7,7 @@ module LunchMoney
|
|
7
7
|
module Calls
|
8
8
|
# https://lunchmoney.dev/#categories
|
9
9
|
class Categories < LunchMoney::Calls::Base
|
10
|
-
# Valid query parameter
|
10
|
+
# Valid query parameter formats for categories
|
11
11
|
VALID_FORMATS = T.let(
|
12
12
|
[
|
13
13
|
"flattened",
|
@@ -24,13 +24,12 @@ module LunchMoney
|
|
24
24
|
def categories(format: nil)
|
25
25
|
response = get("categories", query_params: categories_params(format:))
|
26
26
|
|
27
|
-
|
28
|
-
|
27
|
+
handle_api_response(response) do |body|
|
28
|
+
body[:categories].map do |category|
|
29
|
+
category[:children]&.map! { |child_category| LunchMoney::Objects::Category.new(**child_category) }
|
29
30
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
LunchMoney::Objects::Category.new(**category)
|
31
|
+
LunchMoney::Objects::Category.new(**category)
|
32
|
+
end
|
34
33
|
end
|
35
34
|
end
|
36
35
|
|
@@ -38,12 +37,11 @@ module LunchMoney
|
|
38
37
|
def category(category_id)
|
39
38
|
response = get("categories/#{category_id}")
|
40
39
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
response.body[:children]&.map! { |child_category| LunchMoney::Objects::ChildCategory.new(**child_category) }
|
40
|
+
handle_api_response(response) do |body|
|
41
|
+
body[:children]&.map! { |child_category| LunchMoney::Objects::ChildCategory.new(**child_category) }
|
45
42
|
|
46
|
-
|
43
|
+
LunchMoney::Objects::Category.new(**body)
|
44
|
+
end
|
47
45
|
end
|
48
46
|
|
49
47
|
sig do
|
@@ -70,10 +68,9 @@ module LunchMoney
|
|
70
68
|
})
|
71
69
|
response = post("categories", params)
|
72
70
|
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
response.body
|
71
|
+
handle_api_response(response) do |body|
|
72
|
+
body
|
73
|
+
end
|
77
74
|
end
|
78
75
|
|
79
76
|
sig do
|
@@ -101,10 +98,9 @@ module LunchMoney
|
|
101
98
|
|
102
99
|
response = post("categories/group", params)
|
103
100
|
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
response.body
|
101
|
+
handle_api_response(response) do |body|
|
102
|
+
body
|
103
|
+
end
|
108
104
|
end
|
109
105
|
|
110
106
|
sig do
|
@@ -132,10 +128,9 @@ module LunchMoney
|
|
132
128
|
})
|
133
129
|
response = put("categories/#{category_id}", params)
|
134
130
|
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
response.body
|
131
|
+
handle_api_response(response) do |body|
|
132
|
+
body
|
133
|
+
end
|
139
134
|
end
|
140
135
|
|
141
136
|
sig do
|
@@ -153,30 +148,27 @@ module LunchMoney
|
|
153
148
|
|
154
149
|
response = post("categories/group/#{group_id}/add", params)
|
155
150
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
LunchMoney::Objects::Category.new(**response.body)
|
151
|
+
handle_api_response(response) do |body|
|
152
|
+
LunchMoney::Objects::Category.new(**body)
|
153
|
+
end
|
160
154
|
end
|
161
155
|
|
162
156
|
sig { params(category_id: Integer).returns(T.any(T::Boolean, LunchMoney::Errors)) }
|
163
157
|
def delete_category(category_id)
|
164
158
|
response = delete("categories/#{category_id}")
|
165
159
|
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
response.body
|
160
|
+
handle_api_response(response) do |body|
|
161
|
+
body
|
162
|
+
end
|
170
163
|
end
|
171
164
|
|
172
165
|
sig { params(category_id: Integer).returns(T.any(T::Boolean, LunchMoney::Errors)) }
|
173
166
|
def force_delete_category(category_id)
|
174
167
|
response = delete("categories/#{category_id}/force")
|
175
168
|
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
response.body
|
169
|
+
handle_api_response(response) do |body|
|
170
|
+
body
|
171
|
+
end
|
180
172
|
end
|
181
173
|
|
182
174
|
private
|
@@ -11,11 +11,10 @@ module LunchMoney
|
|
11
11
|
def crypto
|
12
12
|
response = get("crypto")
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
LunchMoney::Objects::Crypto.new(**crypto)
|
14
|
+
handle_api_response(response) do |body|
|
15
|
+
body[:crypto].map do |crypto|
|
16
|
+
LunchMoney::Objects::Crypto.new(**crypto)
|
17
|
+
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
@@ -40,10 +39,9 @@ module LunchMoney
|
|
40
39
|
|
41
40
|
response = put("crypto/manual/#{crypto_id}", params)
|
42
41
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
LunchMoney::Objects::CryptoBase.new(**response.body)
|
42
|
+
handle_api_response(response) do |body|
|
43
|
+
LunchMoney::Objects::CryptoBase.new(**body)
|
44
|
+
end
|
47
45
|
end
|
48
46
|
end
|
49
47
|
end
|
@@ -11,11 +11,10 @@ module LunchMoney
|
|
11
11
|
def plaid_accounts
|
12
12
|
response = get("plaid_accounts")
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
LunchMoney::Objects::PlaidAccount.new(**plaid_account)
|
14
|
+
handle_api_response(response) do |body|
|
15
|
+
body[:plaid_accounts].map do |plaid_account|
|
16
|
+
LunchMoney::Objects::PlaidAccount.new(**plaid_account)
|
17
|
+
end
|
19
18
|
end
|
20
19
|
end
|
21
20
|
|
@@ -30,10 +29,9 @@ module LunchMoney
|
|
30
29
|
params = clean_params({ start_date:, end_date:, plaid_account_id: })
|
31
30
|
response = post("plaid_accounts/fetch", params)
|
32
31
|
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
response.body
|
32
|
+
handle_api_response(response) do |body|
|
33
|
+
body
|
34
|
+
end
|
37
35
|
end
|
38
36
|
end
|
39
37
|
end
|
@@ -17,11 +17,10 @@ module LunchMoney
|
|
17
17
|
params = clean_params({ start_date:, end_date: })
|
18
18
|
response = get("recurring_expenses", query_params: params)
|
19
19
|
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
LunchMoney::Objects::RecurringExpense.new(**recurring_expense)
|
20
|
+
handle_api_response(response) do |body|
|
21
|
+
body[:recurring_expenses].map do |recurring_expense|
|
22
|
+
LunchMoney::Objects::RecurringExpense.new(**recurring_expense)
|
23
|
+
end
|
25
24
|
end
|
26
25
|
end
|
27
26
|
end
|
@@ -11,10 +11,9 @@ module LunchMoney
|
|
11
11
|
def tags
|
12
12
|
response = get("tags")
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
response.body.map { |tag| LunchMoney::Objects::Tag.new(**tag) }
|
14
|
+
handle_api_response(response) do |body|
|
15
|
+
body.map { |tag| LunchMoney::Objects::Tag.new(**tag) }
|
16
|
+
end
|
18
17
|
end
|
19
18
|
end
|
20
19
|
end
|