lunchmoney 1.0.0 → 1.1.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (86) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/check_pipeline.yml +24 -0
  3. data/.github/workflows/ci.yml +1 -4
  4. data/.github/workflows/dependabot-rbi-updater.yml +3 -6
  5. data/.github/workflows/publish_gem.yml +14 -16
  6. data/.github/workflows/release_pipeline.yml +36 -0
  7. data/.rubocop.yml +5 -2
  8. data/Gemfile +1 -1
  9. data/Gemfile.lock +19 -18
  10. data/LICENSE +1 -1
  11. data/README.md +1 -1
  12. data/Rakefile +27 -0
  13. data/lib/lunchmoney/api.rb +160 -35
  14. data/lib/lunchmoney/calls/assets.rb +98 -0
  15. data/lib/lunchmoney/calls/base.rb +118 -0
  16. data/lib/lunchmoney/calls/budgets.rb +84 -0
  17. data/lib/lunchmoney/calls/categories.rb +196 -0
  18. data/lib/lunchmoney/calls/crypto.rb +50 -0
  19. data/lib/lunchmoney/calls/plaid_accounts.rb +40 -0
  20. data/lib/lunchmoney/calls/recurring_expenses.rb +29 -0
  21. data/lib/lunchmoney/calls/tags.rb +21 -0
  22. data/lib/lunchmoney/calls/transactions.rb +220 -0
  23. data/lib/lunchmoney/calls/users.rb +21 -0
  24. data/lib/lunchmoney/errors.rb +17 -1
  25. data/lib/lunchmoney/objects/asset.rb +92 -0
  26. data/lib/lunchmoney/objects/budget.rb +76 -0
  27. data/lib/lunchmoney/objects/category.rb +55 -0
  28. data/lib/lunchmoney/objects/child_category.rb +44 -0
  29. data/lib/lunchmoney/objects/child_transaction.rb +35 -0
  30. data/lib/lunchmoney/objects/config.rb +40 -0
  31. data/lib/lunchmoney/objects/crypto.rb +46 -0
  32. data/lib/lunchmoney/objects/crypto_base.rb +67 -0
  33. data/lib/lunchmoney/objects/data.rb +44 -0
  34. data/lib/lunchmoney/objects/object.rb +28 -0
  35. data/lib/lunchmoney/objects/plaid_account.rb +75 -0
  36. data/lib/lunchmoney/objects/recurring_expense.rb +68 -0
  37. data/lib/lunchmoney/objects/recurring_expense_base.rb +31 -0
  38. data/lib/lunchmoney/objects/split.rb +28 -0
  39. data/lib/lunchmoney/objects/tag.rb +24 -0
  40. data/lib/lunchmoney/objects/tag_base.rb +23 -0
  41. data/lib/lunchmoney/objects/transaction.rb +160 -0
  42. data/lib/lunchmoney/objects/transaction_base.rb +54 -0
  43. data/lib/lunchmoney/objects/transaction_modification_base.rb +32 -0
  44. data/lib/lunchmoney/objects/update_transaction.rb +47 -0
  45. data/lib/lunchmoney/objects/user.rb +38 -0
  46. data/lib/lunchmoney/version.rb +1 -1
  47. data/lunchmoney.gemspec +3 -4
  48. data/sorbet/rbi/gems/{minitest@5.21.2.rbi → minitest@5.22.2.rbi} +147 -144
  49. data/sorbet/rbi/gems/{rubocop-sorbet@0.7.6.rbi → rubocop-sorbet@0.7.7.rbi} +53 -6
  50. data/sorbet/rbi/gems/{rubocop@1.60.1.rbi → rubocop@1.60.2.rbi} +51 -30
  51. data/sorbet/rbi/gems/{toys@0.15.4.rbi → toys@0.15.5.rbi} +3 -3
  52. data/sorbet/rbi/gems/{webmock@3.19.1.rbi → webmock@3.20.0.rbi} +10 -10
  53. metadata +50 -47
  54. data/lib/lunchmoney/api_call.rb +0 -109
  55. data/lib/lunchmoney/assets/asset.rb +0 -89
  56. data/lib/lunchmoney/assets/asset_calls.rb +0 -96
  57. data/lib/lunchmoney/budget/budget.rb +0 -74
  58. data/lib/lunchmoney/budget/budget_calls.rb +0 -82
  59. data/lib/lunchmoney/budget/config.rb +0 -38
  60. data/lib/lunchmoney/budget/data.rb +0 -42
  61. data/lib/lunchmoney/categories/category/category.rb +0 -52
  62. data/lib/lunchmoney/categories/category/child_category.rb +0 -42
  63. data/lib/lunchmoney/categories/category_calls.rb +0 -195
  64. data/lib/lunchmoney/crypto/crypto/crypto.rb +0 -43
  65. data/lib/lunchmoney/crypto/crypto/crypto_base.rb +0 -65
  66. data/lib/lunchmoney/crypto/crypto_calls.rb +0 -49
  67. data/lib/lunchmoney/data_object.rb +0 -25
  68. data/lib/lunchmoney/plaid_accounts/plaid_account.rb +0 -73
  69. data/lib/lunchmoney/plaid_accounts/plaid_account_calls.rb +0 -38
  70. data/lib/lunchmoney/recurring_expenses/recurring_expense/recurring_expense.rb +0 -65
  71. data/lib/lunchmoney/recurring_expenses/recurring_expense/recurring_expense_base.rb +0 -29
  72. data/lib/lunchmoney/recurring_expenses/recurring_expense_calls.rb +0 -28
  73. data/lib/lunchmoney/tags/tag/tag.rb +0 -20
  74. data/lib/lunchmoney/tags/tag/tag_base.rb +0 -21
  75. data/lib/lunchmoney/tags/tag_calls.rb +0 -20
  76. data/lib/lunchmoney/transactions/transaction/child_transaction.rb +0 -31
  77. data/lib/lunchmoney/transactions/transaction/split.rb +0 -24
  78. data/lib/lunchmoney/transactions/transaction/transaction.rb +0 -156
  79. data/lib/lunchmoney/transactions/transaction/transaction_base.rb +0 -52
  80. data/lib/lunchmoney/transactions/transaction/transaction_modification_base.rb +0 -30
  81. data/lib/lunchmoney/transactions/transaction/update_transaction.rb +0 -43
  82. data/lib/lunchmoney/transactions/transaction_calls.rb +0 -218
  83. data/lib/lunchmoney/user/user.rb +0 -36
  84. data/lib/lunchmoney/user/user_calls.rb +0 -19
  85. /data/sorbet/rbi/gems/{crack@0.4.5.rbi → crack@1.0.0.rbi} +0 -0
  86. /data/sorbet/rbi/gems/{toys-core@0.15.4.rbi → toys-core@0.15.5.rbi} +0 -0
@@ -1,89 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module LunchMoney
5
- # https://lunchmoney.dev/#assets-object
6
- class Asset < LunchMoney::DataObject
7
- include LunchMoney::Validators
8
-
9
- sig { returns(Integer) }
10
- attr_accessor :id
11
-
12
- sig { returns(String) }
13
- attr_reader :type_name, :balance_as_of, :created_at
14
-
15
- sig { returns(String) }
16
- attr_accessor :name, :balance, :currency
17
-
18
- sig { returns(T.nilable(String)) }
19
- attr_accessor :display_name, :closed_on, :institution_name, :subtype_name
20
-
21
- sig { returns(T::Boolean) }
22
- attr_accessor :exclude_transactions
23
-
24
- # Valid asset type names
25
- VALID_TYPE_NAMES = T.let(
26
- [
27
- "cash",
28
- "credit",
29
- "investment",
30
- "real estate",
31
- "loan",
32
- "vehicle",
33
- "cryptocurrency",
34
- "employee compensation",
35
- "other liability",
36
- "other asset",
37
- ],
38
- T::Array[String],
39
- )
40
-
41
- sig do
42
- params(
43
- created_at: String,
44
- type_name: String,
45
- name: String,
46
- balance: String,
47
- balance_as_of: String,
48
- currency: String,
49
- exclude_transactions: T::Boolean,
50
- id: Integer,
51
- subtype_name: T.nilable(String),
52
- display_name: T.nilable(String),
53
- closed_on: T.nilable(String),
54
- institution_name: T.nilable(String),
55
- ).void
56
- end
57
- def initialize(created_at:, type_name:, name:, balance:, balance_as_of:, currency:, exclude_transactions:, id:,
58
- subtype_name: nil, display_name: nil, closed_on: nil, institution_name: nil)
59
- super()
60
- @created_at = T.let(validate_iso8601!(created_at), String)
61
- @type_name = T.let(validate_one_of!(type_name, VALID_TYPE_NAMES), String)
62
- @name = name
63
- @balance = balance
64
- @balance_as_of = T.let(validate_iso8601!(balance_as_of), String)
65
- @currency = currency
66
- @exclude_transactions = exclude_transactions
67
- @id = id
68
- @subtype_name = subtype_name
69
- @display_name = display_name
70
- @closed_on = closed_on
71
- @institution_name = institution_name
72
- end
73
-
74
- sig { params(name: String).void }
75
- def type_name=(name)
76
- @type_name = validate_one_of!(name, VALID_TYPE_NAMES)
77
- end
78
-
79
- sig { params(time: String).void }
80
- def balance_as_of=(time)
81
- @balance_as_of = validate_iso8601!(time)
82
- end
83
-
84
- sig { params(time: String).void }
85
- def created_at=(time)
86
- @created_at = validate_iso8601!(time)
87
- end
88
- end
89
- end
@@ -1,96 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require_relative "asset"
5
-
6
- module LunchMoney
7
- # https://lunchmoney.dev/#assets
8
- class AssetCalls < ApiCall
9
- sig { returns(T.any(T::Array[LunchMoney::Asset], LunchMoney::Errors)) }
10
- def assets
11
- response = get("assets")
12
-
13
- api_errors = errors(response)
14
- return api_errors if api_errors.present?
15
-
16
- response.body[:assets].map do |asset|
17
- LunchMoney::Asset.new(**asset)
18
- end
19
- end
20
-
21
- sig do
22
- params(
23
- type_name: String,
24
- name: String,
25
- balance: String,
26
- subtype_name: T.nilable(String),
27
- display_name: T.nilable(String),
28
- balance_as_of: T.nilable(String),
29
- currency: T.nilable(String),
30
- institution_name: T.nilable(String),
31
- closed_on: T.nilable(String),
32
- exclude_transactions: T.nilable(T::Boolean),
33
- ).returns(T.any(LunchMoney::Asset, LunchMoney::Errors))
34
- end
35
- def create_asset(type_name:, name:, balance:, subtype_name: nil, display_name: nil, balance_as_of: nil,
36
- currency: nil, institution_name: nil, closed_on: nil, exclude_transactions: nil)
37
- params = {
38
- type_name:,
39
- name:,
40
- balance:,
41
- subtype_name:,
42
- display_name:,
43
- balance_as_of:,
44
- currency:,
45
- institution_name:,
46
- closed_on:,
47
- exclude_transactions:,
48
- }
49
-
50
- response = post("assets", params)
51
-
52
- api_errors = errors(response)
53
- return api_errors if api_errors.present?
54
-
55
- LunchMoney::Asset.new(**response.body)
56
- end
57
-
58
- sig do
59
- params(
60
- asset_id: Integer,
61
- type_name: T.nilable(String),
62
- name: T.nilable(String),
63
- balance: T.nilable(String),
64
- subtype_name: T.nilable(String),
65
- display_name: T.nilable(String),
66
- balance_as_of: T.nilable(String),
67
- currency: T.nilable(String),
68
- institution_name: T.nilable(String),
69
- closed_on: T.nilable(String),
70
- exclude_transactions: T.nilable(T::Boolean),
71
- ).returns(T.any(LunchMoney::Asset, LunchMoney::Errors))
72
- end
73
- def update_asset(asset_id, type_name: nil, name: nil, balance: nil, subtype_name: nil, display_name: nil,
74
- balance_as_of: nil, currency: nil, institution_name: nil, closed_on: nil, exclude_transactions: nil)
75
- params = {
76
- type_name:,
77
- name:,
78
- balance:,
79
- subtype_name:,
80
- display_name:,
81
- balance_as_of:,
82
- currency:,
83
- institution_name:,
84
- closed_on:,
85
- exclude_transactions:,
86
- }
87
-
88
- response = put("assets/#{asset_id}", params)
89
-
90
- api_errors = errors(response)
91
- return api_errors if api_errors.present?
92
-
93
- LunchMoney::Asset.new(**response.body)
94
- end
95
- end
96
- end
@@ -1,74 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require_relative "data"
5
- require_relative "config"
6
-
7
- module LunchMoney
8
- # https://lunchmoney.dev/#budget-object
9
- class Budget < LunchMoney::DataObject
10
- # API object reference documentation: https://lunchmoney.dev/#budget-object
11
-
12
- sig { returns(String) }
13
- attr_accessor :category_name
14
-
15
- sig { returns(Integer) }
16
- attr_accessor :order
17
-
18
- sig { returns(T.nilable(String)) }
19
- attr_accessor :category_group_name
20
-
21
- sig { returns(T.nilable(Integer)) }
22
- attr_accessor :category_id, :group_id
23
-
24
- sig { returns(T.nilable(T::Boolean)) }
25
- attr_accessor :is_group
26
-
27
- sig { returns(T::Boolean) }
28
- attr_accessor :is_income, :exclude_from_budget, :exclude_from_totals, :archived
29
-
30
- sig { returns(T::Hash[Symbol, LunchMoney::Data]) }
31
- attr_accessor :data
32
-
33
- sig { returns(T.nilable(T::Hash[Symbol, LunchMoney::Config])) }
34
- attr_accessor :config
35
-
36
- sig { returns(T.nilable({ list: T::Array[LunchMoney::RecurringExpense] })) }
37
- attr_accessor :recurring
38
-
39
- sig do
40
- params(
41
- is_income: T::Boolean,
42
- exclude_from_budget: T::Boolean,
43
- exclude_from_totals: T::Boolean,
44
- data: T::Hash[Symbol, LunchMoney::Data],
45
- category_name: String,
46
- order: Integer,
47
- archived: T::Boolean,
48
- category_id: T.nilable(Integer),
49
- category_group_name: T.nilable(String),
50
- group_id: T.nilable(Integer),
51
- is_group: T.nilable(T::Boolean),
52
- config: T.nilable(T::Hash[Symbol, LunchMoney::Config]),
53
- recurring: T.nilable({ list: T::Array[LunchMoney::RecurringExpense] }),
54
- ).void
55
- end
56
- def initialize(is_income:, exclude_from_budget:, exclude_from_totals:, data:, category_name:, order:, archived:,
57
- category_id: nil, category_group_name: nil, group_id: nil, is_group: nil, config: nil, recurring: nil)
58
- super()
59
- @category_id = category_id
60
- @is_income = is_income
61
- @exclude_from_budget = exclude_from_budget
62
- @exclude_from_totals = exclude_from_totals
63
- @data = data
64
- @category_name = category_name
65
- @order = order
66
- @category_group_name = category_group_name
67
- @group_id = group_id
68
- @is_group = is_group
69
- @config = config
70
- @archived = archived
71
- @recurring = recurring
72
- end
73
- end
74
- end
@@ -1,82 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- require_relative "budget"
5
-
6
- module LunchMoney
7
- # https://lunchmoney.dev/#budget
8
- class BudgetCalls < ApiCall
9
- sig do
10
- params(
11
- start_date: String,
12
- end_date: String,
13
- currency: T.nilable(String),
14
- ).returns(T.any(T::Array[LunchMoney::Budget], LunchMoney::Errors))
15
- end
16
- def budgets(start_date:, end_date:, currency: nil)
17
- params = clean_params({ start_date:, end_date:, currency: })
18
- response = get("budgets", query_params: params)
19
-
20
- api_errors = errors(response)
21
- return api_errors if api_errors.present?
22
-
23
- response.body.map do |budget|
24
- if budget[:data]
25
- data_keys = budget[:data].keys
26
- data_keys.each do |data_key|
27
- budget[:data][data_key] = LunchMoney::Data.new(**budget[:data][data_key])
28
- end
29
- end
30
-
31
- if budget[:config]
32
- config_keys = budget[:config].keys
33
- config_keys.each do |config_key|
34
- budget[:config][config_key] = LunchMoney::Data.new(**budget[:config][config_key])
35
- end
36
- end
37
-
38
- if budget[:recurring]
39
- budget[:recurring][:list]&.map! { |recurring| LunchMoney::RecurringExpenseBase.new(**recurring) }
40
- end
41
-
42
- LunchMoney::Budget.new(**budget)
43
- end
44
- end
45
-
46
- sig do
47
- params(
48
- start_date: String,
49
- category_id: Integer,
50
- amount: Number,
51
- currency: T.nilable(String),
52
- ).returns(T.any(
53
- T::Hash[Symbol, { category_id: Integer, amount: Number, currency: String, start_date: String }],
54
- LunchMoney::Errors,
55
- ))
56
- end
57
- def upsert_budget(start_date:, category_id:, amount:, currency: nil)
58
- params = clean_params({ start_date:, category_id:, amount:, currency: })
59
- response = put("budgets", params)
60
-
61
- api_errors = errors(response)
62
- return api_errors if api_errors.present?
63
-
64
- response.body
65
- end
66
-
67
- sig { params(start_date: String, category_id: Integer).returns(T.any(T::Boolean, LunchMoney::Errors)) }
68
- def remove_budget(start_date:, category_id:)
69
- params = {
70
- start_date:,
71
- category_id:,
72
- }
73
-
74
- response = delete("budgets", query_params: params)
75
-
76
- api_errors = errors(response)
77
- return api_errors if api_errors.present?
78
-
79
- response.body
80
- end
81
- end
82
- end
@@ -1,38 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module LunchMoney
5
- # https://lunchmoney.dev/#config-object
6
- class Config < LunchMoney::DataObject
7
- # API object reference documentation: https://lunchmoney.dev/#config-object
8
-
9
- sig { returns(Integer) }
10
- attr_accessor :config_id
11
-
12
- sig { returns(Number) }
13
- attr_accessor :amount, :to_base
14
-
15
- sig { returns(String) }
16
- attr_accessor :cadence, :currency, :auto_suggest
17
-
18
- sig do
19
- params(
20
- config_id: Integer,
21
- cadence: String,
22
- amount: Number,
23
- currency: String,
24
- to_base: Number,
25
- auto_suggest: String,
26
- ).void
27
- end
28
- def initialize(config_id:, cadence:, amount:, currency:, to_base:, auto_suggest:)
29
- super()
30
- @config_id = config_id
31
- @cadence = cadence
32
- @amount = amount
33
- @currency = currency
34
- @to_base = to_base
35
- @auto_suggest = auto_suggest
36
- end
37
- end
38
- end
@@ -1,42 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module LunchMoney
5
- # https://lunchmoney.dev/#data-object
6
- class Data < LunchMoney::DataObject
7
- # API object reference documentation: https://lunchmoney.dev/#data-object
8
-
9
- sig { returns(T.nilable(Integer)) }
10
- attr_accessor :num_transactions
11
-
12
- sig { returns(T.nilable(Number)) }
13
- attr_accessor :budget_amount, :budget_to_base, :spending_to_base
14
-
15
- sig { returns(T.nilable(String)) }
16
- attr_accessor :budget_currency
17
-
18
- sig { returns(T.nilable(T::Boolean)) }
19
- attr_accessor :is_automated
20
-
21
- sig do
22
- params(
23
- spending_to_base: T.nilable(Number),
24
- num_transactions: T.nilable(Integer),
25
- budget_amount: T.nilable(Number),
26
- budget_currency: T.nilable(String),
27
- budget_to_base: T.nilable(Number),
28
- is_automated: T.nilable(T::Boolean),
29
- ).void
30
- end
31
- def initialize(spending_to_base: nil, num_transactions: nil, budget_amount: nil, budget_currency: nil,
32
- budget_to_base: nil, is_automated: nil)
33
- super()
34
- @budget_amount = budget_amount
35
- @budget_currency = budget_currency
36
- @budget_to_base = budget_to_base
37
- @spending_to_base = spending_to_base
38
- @num_transactions = num_transactions
39
- @is_automated = is_automated
40
- end
41
- end
42
- end
@@ -1,52 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module LunchMoney
5
- # https://lunchmoney.dev/#categories-object
6
- class Category < ChildCategory
7
- sig { returns(T.nilable(String)) }
8
- attr_accessor :group_category_name
9
-
10
- sig { returns(T::Boolean) }
11
- attr_accessor :is_income, :exclude_from_budget, :exclude_from_totals, :is_group
12
-
13
- sig { returns(T.nilable(Integer)) }
14
- attr_accessor :group_id, :order
15
-
16
- sig { returns(T.nilable(T::Array[T.any(LunchMoney::Category, LunchMoney::ChildCategory)])) }
17
- attr_accessor :children
18
-
19
- sig do
20
- params(
21
- id: Integer,
22
- name: String,
23
- is_income: T::Boolean,
24
- exclude_from_budget: T::Boolean,
25
- exclude_from_totals: T::Boolean,
26
- is_group: T::Boolean,
27
- archived: T.nilable(T::Boolean),
28
- archived_on: T.nilable(String),
29
- updated_at: T.nilable(String),
30
- created_at: T.nilable(String),
31
- group_id: T.nilable(Integer),
32
- order: T.nilable(Integer),
33
- description: T.nilable(String),
34
- children: T.nilable(T::Array[T.any(LunchMoney::Category, LunchMoney::ChildCategory)]),
35
- group_category_name: T.nilable(String),
36
- ).void
37
- end
38
- def initialize(id:, name:, is_income:, exclude_from_budget:, exclude_from_totals:, is_group:, archived: nil,
39
- archived_on: nil, updated_at: nil, created_at: nil, group_id: nil, order: nil, description: nil, children: nil,
40
- group_category_name: nil)
41
- super(id:, name:, archived:, archived_on:, updated_at:, created_at:, description:)
42
- @is_income = is_income
43
- @exclude_from_budget = exclude_from_budget
44
- @exclude_from_totals = exclude_from_totals
45
- @is_group = is_group
46
- @group_id = group_id
47
- @order = order
48
- @children = children
49
- @group_category_name = group_category_name
50
- end
51
- end
52
- end
@@ -1,42 +0,0 @@
1
- # typed: strict
2
- # frozen_string_literal: true
3
-
4
- module LunchMoney
5
- # A slimmed down version of https://lunchmoney.dev/#categories-object used in the
6
- # `children` field of some category calls
7
- class ChildCategory < LunchMoney::DataObject
8
- sig { returns(Integer) }
9
- attr_accessor :id
10
-
11
- sig { returns(String) }
12
- attr_accessor :name
13
-
14
- sig { returns(T.nilable(String)) }
15
- attr_accessor :description, :archived_on, :updated_at, :created_at
16
-
17
- sig { returns(T.nilable(T::Boolean)) }
18
- attr_accessor :archived
19
-
20
- sig do
21
- params(
22
- id: Integer,
23
- name: String,
24
- archived: T.nilable(T::Boolean),
25
- archived_on: T.nilable(String),
26
- updated_at: T.nilable(String),
27
- created_at: T.nilable(String),
28
- description: T.nilable(String),
29
- ).void
30
- end
31
- def initialize(id:, name:, archived: nil, archived_on: nil, updated_at: nil, created_at: nil, description: nil)
32
- super()
33
- @id = id
34
- @name = name
35
- @archived = archived
36
- @archived_on = archived_on
37
- @updated_at = updated_at
38
- @created_at = created_at
39
- @description = description
40
- end
41
- end
42
- end