ledger_sync 1.0.10 → 1.1.1

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.
Files changed (115) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile.lock +36 -20
  3. data/README.md +105 -66
  4. data/ledger_sync.gemspec +1 -0
  5. data/lib/ledger_sync.rb +23 -4
  6. data/lib/ledger_sync/adaptors/operation.rb +28 -28
  7. data/lib/ledger_sync/adaptors/quickbooks_online/account/mapping.rb +325 -0
  8. data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/create.rb +54 -0
  9. data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/find.rb +38 -0
  10. data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/update.rb +61 -0
  11. data/lib/ledger_sync/adaptors/quickbooks_online/account/searcher.rb +67 -0
  12. data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +18 -16
  13. data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/create.rb +65 -0
  14. data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/find.rb +37 -0
  15. data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/update.rb +69 -0
  16. data/lib/ledger_sync/adaptors/quickbooks_online/bill/searcher.rb +28 -0
  17. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +6 -6
  18. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +1 -3
  19. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +6 -9
  20. data/lib/ledger_sync/adaptors/quickbooks_online/customer/searcher.rb +2 -38
  21. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/create.rb +61 -0
  22. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/find.rb +36 -0
  23. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/update.rb +65 -0
  24. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/searcher.rb +28 -0
  25. data/lib/ledger_sync/adaptors/quickbooks_online/expense/mapping.rb +15 -0
  26. data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/create.rb +68 -0
  27. data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/find.rb +39 -0
  28. data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/update.rb +72 -0
  29. data/lib/ledger_sync/adaptors/quickbooks_online/expense/searcher.rb +28 -0
  30. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/mapping.rb +14 -0
  31. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/create.rb +56 -0
  32. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/find.rb +34 -0
  33. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/update.rb +60 -0
  34. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/searcher.rb +28 -0
  35. data/lib/ledger_sync/adaptors/quickbooks_online/operation.rb +30 -0
  36. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +8 -22
  37. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +0 -2
  38. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +6 -22
  39. data/lib/ledger_sync/adaptors/quickbooks_online/searcher.rb +45 -0
  40. data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/create.rb +52 -0
  41. data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/find.rb +36 -0
  42. data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/update.rb +57 -0
  43. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/create.rb +46 -0
  44. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/find.rb +36 -0
  45. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/update.rb +51 -0
  46. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/searcher.rb +64 -0
  47. data/lib/ledger_sync/adaptors/searcher.rb +3 -1
  48. data/lib/ledger_sync/adaptors/test/account/operations/create.rb +53 -0
  49. data/lib/ledger_sync/adaptors/test/account/operations/find.rb +38 -0
  50. data/lib/ledger_sync/adaptors/test/account/operations/invalid.rb +25 -0
  51. data/lib/ledger_sync/adaptors/test/account/operations/update.rb +50 -0
  52. data/lib/ledger_sync/adaptors/test/account/operations/valid.rb +31 -0
  53. data/lib/ledger_sync/adaptors/test/account/searcher.rb +40 -0
  54. data/lib/ledger_sync/adaptors/test/adaptor.rb +4 -4
  55. data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +4 -6
  56. data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +0 -2
  57. data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +4 -6
  58. data/lib/ledger_sync/adaptors/test/customer/searcher.rb +2 -2
  59. data/lib/ledger_sync/adaptors/test/expense/operations/create.rb +54 -0
  60. data/lib/ledger_sync/adaptors/test/expense/operations/find.rb +39 -0
  61. data/lib/ledger_sync/adaptors/test/expense/operations/update.rb +57 -0
  62. data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +4 -20
  63. data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +0 -2
  64. data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +4 -20
  65. data/lib/ledger_sync/adaptors/test/transfer/operations/create.rb +45 -0
  66. data/lib/ledger_sync/adaptors/test/transfer/operations/find.rb +36 -0
  67. data/lib/ledger_sync/adaptors/test/transfer/operations/update.rb +48 -0
  68. data/lib/ledger_sync/adaptors/test/vendor/operations/create.rb +47 -0
  69. data/lib/ledger_sync/adaptors/test/vendor/operations/find.rb +34 -0
  70. data/lib/ledger_sync/adaptors/test/vendor/operations/invalid.rb +21 -0
  71. data/lib/ledger_sync/adaptors/test/vendor/operations/update.rb +44 -0
  72. data/lib/ledger_sync/adaptors/test/vendor/operations/valid.rb +27 -0
  73. data/lib/ledger_sync/adaptors/test/vendor/searcher.rb +41 -0
  74. data/lib/ledger_sync/error/resource_errors.rb +24 -0
  75. data/lib/ledger_sync/resource.rb +24 -64
  76. data/lib/ledger_sync/resource_attribute.rb +50 -0
  77. data/lib/ledger_sync/resource_attribute/dirty_mixin.rb +49 -0
  78. data/lib/ledger_sync/resource_attribute/mixin.rb +90 -0
  79. data/lib/ledger_sync/resource_attribute/reference.rb +9 -0
  80. data/lib/ledger_sync/resource_attribute/reference/many.rb +34 -0
  81. data/lib/ledger_sync/resource_attribute/reference/one.rb +33 -0
  82. data/lib/ledger_sync/resource_attribute_set.rb +58 -0
  83. data/lib/ledger_sync/resources/account.rb +14 -0
  84. data/lib/ledger_sync/resources/bill.rb +17 -0
  85. data/lib/ledger_sync/resources/bill_line_item.rb +11 -0
  86. data/lib/ledger_sync/resources/customer.rb +5 -4
  87. data/lib/ledger_sync/resources/deposit.rb +16 -0
  88. data/lib/ledger_sync/resources/deposit_line_item.rb +11 -0
  89. data/lib/ledger_sync/resources/expense.rb +19 -0
  90. data/lib/ledger_sync/resources/expense_line_item.rb +11 -0
  91. data/lib/ledger_sync/resources/journal_entry.rb +13 -0
  92. data/lib/ledger_sync/resources/journal_entry_line_item.rb +12 -0
  93. data/lib/ledger_sync/resources/payment.rb +5 -3
  94. data/lib/ledger_sync/resources/transfer.rb +15 -0
  95. data/lib/ledger_sync/resources/vendor.rb +12 -0
  96. data/lib/ledger_sync/result.rb +0 -24
  97. data/lib/ledger_sync/type/boolean.rb +17 -0
  98. data/lib/ledger_sync/type/date.rb +17 -0
  99. data/lib/ledger_sync/type/float.rb +17 -0
  100. data/lib/ledger_sync/type/integer.rb +17 -0
  101. data/lib/ledger_sync/type/reference_many.rb +27 -0
  102. data/lib/ledger_sync/type/reference_one.rb +26 -0
  103. data/lib/ledger_sync/type/string.rb +17 -0
  104. data/lib/ledger_sync/type/value.rb +12 -0
  105. data/lib/ledger_sync/type/value_mixin.rb +19 -0
  106. data/lib/ledger_sync/util/hash_helpers.rb +16 -1
  107. data/lib/ledger_sync/util/resources_builder.rb +36 -9
  108. data/lib/ledger_sync/version.rb +1 -1
  109. metadata +92 -7
  110. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/upsert.rb +0 -42
  111. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/upsert.rb +0 -53
  112. data/lib/ledger_sync/adaptors/test/customer/operations/upsert.rb +0 -42
  113. data/lib/ledger_sync/adaptors/test/payment/operations/upsert.rb +0 -53
  114. data/lib/ledger_sync/sync.rb +0 -108
  115. data/lib/ledger_sync/util/coordinator.rb +0 -72
@@ -0,0 +1,38 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Account
5
+ module Operations
6
+ class Find < Operation::Find
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ params do
9
+ required(:ledger_id).filled(:string)
10
+ required(:name).maybe(:string)
11
+ required(:classification).maybe(:string)
12
+ required(:account_type).maybe(:string)
13
+ required(:account_sub_type).maybe(:string)
14
+ required(:number).maybe(:integer)
15
+ required(:currency).maybe(:string)
16
+ required(:description).maybe(:string)
17
+ required(:active).maybe(:bool)
18
+ end
19
+ end
20
+
21
+ private
22
+
23
+ def operate
24
+ return failure(nil) if resource.ledger_id.nil?
25
+
26
+ response = adaptor.find(
27
+ resource: 'account',
28
+ id: resource.ledger_id
29
+ )
30
+
31
+ success(response: response)
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,61 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'ledger_sync/adaptors/quickbooks_online/account/mapping'
4
+
5
+ module LedgerSync
6
+ module Adaptors
7
+ module QuickBooksOnline
8
+ module Account
9
+ module Operations
10
+ class Update < Operation::Update
11
+ class Contract < LedgerSync::Adaptors::Contract
12
+ params do
13
+ required(:ledger_id).filled(:string)
14
+ required(:name).filled(:string)
15
+ required(:classification).filled(:string)
16
+ required(:account_type).filled(:string)
17
+ required(:account_sub_type).filled(:string)
18
+ required(:number).maybe(:integer)
19
+ required(:currency).maybe(:string)
20
+ required(:description).maybe(:string)
21
+ required(:active).maybe(:bool)
22
+ end
23
+ end
24
+
25
+ private
26
+
27
+ def operate
28
+ ledger_resource_data = adaptor.find(
29
+ resource: 'account',
30
+ id: resource.ledger_id
31
+ )
32
+
33
+ response = adaptor.post(
34
+ resource: 'account',
35
+ payload: merge_into(from: local_resource_data, to: ledger_resource_data)
36
+ )
37
+
38
+ resource.ledger_id = response.dig('Id')
39
+ success(response: response)
40
+ end
41
+
42
+ def local_resource_data
43
+ {
44
+ 'Name' => resource.name,
45
+ 'Classification' => Mapping::ACCOUNT_CLASSIFICATIONS[resource.classification],
46
+ 'AccountType' => Mapping::ACCOUNT_TYPES[resource.account_type],
47
+ 'AccountSubType' => Mapping::ACCOUNT_SUB_TYPES[resource.account_sub_type],
48
+ 'AcctNum' => resource.number,
49
+ 'CurrencyRef' => {
50
+ 'value' => resource.currency,
51
+ },
52
+ 'Description' => resource.description,
53
+ 'Active' => resource.active
54
+ }
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
@@ -0,0 +1,67 @@
1
+ require 'ledger_sync/adaptors/quickbooks_online/account/mapping'
2
+
3
+ module LedgerSync
4
+ module Adaptors
5
+ module QuickBooksOnline
6
+ module Account
7
+ class Searcher < LedgerSync::Adaptors::Searcher
8
+ def next_searcher
9
+ paginate(limit: limit, offset: offset + limit)
10
+ end
11
+
12
+ def previous_searcher
13
+ return nil if offset <= 1
14
+
15
+ paginate(limit: limit, offset: offset - limit)
16
+ end
17
+
18
+ def resources
19
+ @resources ||= begin
20
+ adaptor
21
+ .query(
22
+ resource: 'account',
23
+ query: "Name LIKE '%#{query}%'",
24
+ limit: limit,
25
+ offset: offset
26
+ )
27
+ .map do |c|
28
+ LedgerSync::Account.new(
29
+ ledger_id: c.fetch('Id'),
30
+ name: c.fetch('Name'),
31
+ classification: Mapping::ACCOUNT_CLASSIFICATIONS.invert[c.fetch('Classification')] || c.fetch('Classification'),
32
+ account_type: Mapping::ACCOUNT_TYPES.invert[c.fetch('AccountType')] || c.fetch('AccountType'),
33
+ account_sub_type: Mapping::ACCOUNT_SUB_TYPES.invert[c.fetch('AccountSubType')] || c.fetch('AccountSubType')
34
+ )
35
+ end
36
+ end
37
+ end
38
+
39
+ def search
40
+ super
41
+ rescue OAuth2::Error => e
42
+ @response = e # TODO: Better catch/raise errors as LedgerSync::Error
43
+ failure
44
+ end
45
+
46
+ private
47
+ # Pagination uses notation of limit and offset
48
+ # limit: number of results per page
49
+ #
50
+ # offset: position of first result in a list.
51
+ # starts from 1, not 0
52
+ #
53
+ # More here:
54
+ # https://developer.intuit.com/app/developer/qbo/docs/develop/explore-the-quickbooks-online-api/data-queries#pagination
55
+
56
+ def limit
57
+ pagination.fetch(:limit, 10).to_i
58
+ end
59
+
60
+ def offset
61
+ pagination.fetch(:offset, 1).to_i
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -19,6 +19,7 @@ module LedgerSync
19
19
  :previous_refresh_tokens,
20
20
  :realm_id,
21
21
  :refresh_token,
22
+ :refresh_token_expires_at,
22
23
  :root_uri,
23
24
  :test
24
25
 
@@ -43,10 +44,10 @@ module LedgerSync
43
44
  end
44
45
 
45
46
  def find(resource:, id:)
46
- url = "#{oauth_base_uri}/#{underscore(resource)}/#{id}"
47
+ url = "#{oauth_base_uri}/#{resourcify(resource)}/#{id}"
47
48
 
48
49
  response = request(:get, url, headers: OAUTH_HEADERS.dup)
49
- JSON.parse(response.body).dig(resource.capitalize)
50
+ JSON.parse(response.body).dig(resource.classify)
50
51
  end
51
52
 
52
53
  def parse_operation_error(error:, operation:)
@@ -58,12 +59,19 @@ module LedgerSync
58
59
  ).parse
59
60
  end
60
61
 
62
+ def post(resource:, payload:)
63
+ url = "#{oauth_base_uri}/#{resourcify(resource)}"
64
+
65
+ response = request(:post, url, headers: OAUTH_HEADERS.dup, body: payload.to_json)
66
+ JSON.parse(response.body).dig(resource.classify)
67
+ end
68
+
61
69
  def query(resource:, query:, limit: 10, offset: 1)
62
- full_query = "SELECT * FROM #{resource.capitalize} WHERE #{query} STARTPOSITION #{offset} MAXRESULTS #{limit}"
70
+ full_query = "SELECT * FROM #{resource.classify} WHERE #{query} STARTPOSITION #{offset} MAXRESULTS #{limit}"
63
71
  url = "#{oauth_base_uri}/query?query=#{CGI.escape(full_query)}"
64
72
 
65
73
  response = request(:get, url, headers: OAUTH_HEADERS.dup)
66
- JSON.parse(response.body).dig('QueryResponse', resource.capitalize) || []
74
+ JSON.parse(response.body).dig('QueryResponse', resource.classify) || []
67
75
  end
68
76
 
69
77
  def refresh!
@@ -73,6 +81,7 @@ module LedgerSync
73
81
  @access_token = refreshed.token
74
82
 
75
83
  @expires_at = Time&.at(refreshed.expires_at.to_i)&.to_datetime
84
+ @refresh_token_expires_at = Time&.at(Time.now.to_i + refreshed.params['x_refresh_token_expires_in'])&.to_datetime unless refreshed.params['x_refresh_token_expires_in'].nil?
76
85
 
77
86
  @previous_refresh_tokens << refresh_token
78
87
  @refresh_token = refreshed.refresh_token
@@ -84,15 +93,8 @@ module LedgerSync
84
93
  raise parse_error(error: e)
85
94
  end
86
95
 
87
- def upsert(resource:, payload:)
88
- url = "#{oauth_base_uri}/#{underscore(resource)}"
89
-
90
- response = request(:post, url, headers: OAUTH_HEADERS.dup, body: payload.to_json)
91
- JSON.parse(response.body).dig(resource.capitalize)
92
- end
93
-
94
96
  def self.ledger_attributes_to_save
95
- %i[access_token expires_at refresh_token]
97
+ %i[access_token expires_at refresh_token refresh_token_expires_at]
96
98
  end
97
99
 
98
100
  # def self.url_for(resource:)
@@ -108,10 +110,6 @@ module LedgerSync
108
110
  @oauth_base_uri ||= "#{root_uri}/v3/company/#{realm_id}"
109
111
  end
110
112
 
111
- def underscore(str)
112
- LedgerSync::Util::StringHelpers.underscore(str)
113
- end
114
-
115
113
  def oauth(force: false)
116
114
  if @oauth.nil? || force
117
115
  @oauth = OAuth2::AccessToken.new(
@@ -154,6 +152,10 @@ module LedgerSync
154
152
  adaptor: self
155
153
  ).parse
156
154
  end
155
+
156
+ def resourcify(str)
157
+ str.tr('_', '')
158
+ end
157
159
  end
158
160
  end
159
161
  end
@@ -0,0 +1,65 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Bill
5
+ module Operations
6
+ class Create < Operation::Create
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ params do
9
+ required(:ledger_id).value(:nil)
10
+ required(:vendor).hash(Types::Reference)
11
+ required(:account).hash(Types::Reference)
12
+ required(:currency).filled(:string)
13
+ required(:memo).maybe(:string)
14
+ required(:transaction_date).maybe(:date?)
15
+ required(:due_date).maybe(:date?)
16
+ required(:line_items).array(Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ response = adaptor.post(
24
+ resource: 'bill',
25
+ payload: local_resource_data
26
+ )
27
+
28
+ resource.ledger_id = response.dig('Id')
29
+ success(response: response)
30
+ end
31
+
32
+ def local_resource_data
33
+ {
34
+ 'CurrencyRef' => {
35
+ 'value' => resource.currency,
36
+ },
37
+ 'TxnDate' => resource.transaction_date.to_s, # Format: YYYY-MM-DD
38
+ 'DueDate' => resource.due_date.to_s, # Format: YYYY-MM-DD
39
+ 'PrivateNote' => resource.memo,
40
+ 'VendorRef' => {
41
+ 'value' => resource.vendor.ledger_id,
42
+ },
43
+ 'APAccountRef' => {
44
+ 'value' => resource.account.ledger_id
45
+ },
46
+ 'Line' => resource.line_items.map do |line_item|
47
+ {
48
+ 'DetailType' => 'AccountBasedExpenseLineDetail',
49
+ 'AccountBasedExpenseLineDetail' => {
50
+ 'AccountRef' => {
51
+ 'value' => line_item.account&.ledger_id
52
+ }
53
+ },
54
+ 'Amount' => line_item.amount / 100.0,
55
+ 'Description' => line_item.description
56
+ }
57
+ end
58
+ }
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
@@ -0,0 +1,37 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Bill
5
+ module Operations
6
+ class Find < Operation::Find
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ schema do
9
+ required(:ledger_id).filled(:string)
10
+ required(:vendor).hash(Types::Reference)
11
+ required(:account).hash(Types::Reference)
12
+ required(:currency).maybe(:string)
13
+ required(:memo).maybe(:string)
14
+ required(:transaction_date).maybe(:date?)
15
+ required(:due_date).maybe(:date?)
16
+ required(:line_items).array(Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ return failure(nil) if resource.ledger_id.nil?
24
+
25
+ response = adaptor.find(
26
+ resource: 'bill',
27
+ id: resource.ledger_id
28
+ )
29
+
30
+ success(response: response)
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,69 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Bill
5
+ module Operations
6
+ class Update < Operation::Update
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ schema do
9
+ required(:ledger_id).filled(:string)
10
+ required(:vendor).hash(Types::Reference)
11
+ required(:account).hash(Types::Reference)
12
+ required(:currency).filled(:string)
13
+ required(:memo).maybe(:string)
14
+ required(:transaction_date).maybe(:date?)
15
+ required(:due_date).maybe(:date?)
16
+ required(:line_items).array(Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ ledger_resource_data = adaptor.find(
24
+ resource: 'bill',
25
+ id: resource.ledger_id
26
+ )
27
+ response = adaptor.post(
28
+ resource: 'bill',
29
+ payload: merge_into(from: local_resource_data, to: ledger_resource_data)
30
+ )
31
+
32
+ resource.ledger_id = response.dig('Id')
33
+ success(response: response)
34
+ end
35
+
36
+ def local_resource_data
37
+ {
38
+ 'CurrencyRef' => {
39
+ 'value' => resource.currency,
40
+ },
41
+ 'TxnDate' => resource.transaction_date.to_s, # Format: YYYY-MM-DD
42
+ 'DueDate' => resource.due_date.to_s, # Format: YYYY-MM-DD
43
+ 'PrivateNote' => resource.memo,
44
+ 'VendorRef' => {
45
+ 'value' => resource.vendor.ledger_id,
46
+ },
47
+ 'APAccountRef' => {
48
+ 'value' => resource.account.ledger_id
49
+ },
50
+ 'Line' => resource.line_items.map do |line_item|
51
+ {
52
+ 'DetailType' => 'AccountBasedExpenseLineDetail',
53
+ 'AccountBasedExpenseLineDetail' => {
54
+ 'AccountRef' => {
55
+ 'value' => line_item.account&.ledger_id
56
+ }
57
+ },
58
+ 'Amount' => line_item.amount / 100.0,
59
+ 'Description' => line_item.description
60
+ }
61
+ end
62
+ }
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,28 @@
1
+ # frozen_string_literal: true
2
+ require_relative '../searcher'
3
+
4
+ module LedgerSync
5
+ module Adaptors
6
+ module QuickBooksOnline
7
+ module Bill
8
+ class Searcher < QuickBooksOnline::Searcher
9
+ def resources
10
+ @resources ||= begin
11
+ adaptor
12
+ .query(
13
+ resource: 'bill',
14
+ limit: limit,
15
+ offset: offset
16
+ )
17
+ .map do |c|
18
+ LedgerSync::Bill.new(
19
+ ledger_id: c.fetch('Id')
20
+ )
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end