ledger_sync 1.1.3 → 1.3.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 (216) hide show
  1. checksums.yaml +4 -4
  2. data/.env.template +25 -0
  3. data/.gitignore +3 -1
  4. data/.rubocop_todo.yml +4 -1
  5. data/.travis.yml +1 -1
  6. data/Gemfile.lock +59 -25
  7. data/README.md +160 -8
  8. data/_config.yml +1 -0
  9. data/bin/qa +3 -0
  10. data/ledger_sync.gemspec +4 -0
  11. data/lib/ledger_sync.rb +40 -30
  12. data/lib/ledger_sync/adaptor_configuration.rb +17 -11
  13. data/lib/ledger_sync/adaptor_configuration_store.rb +13 -9
  14. data/lib/ledger_sync/adaptors/adaptor.rb +9 -1
  15. data/lib/ledger_sync/adaptors/ledger_serializer.rb +3 -6
  16. data/lib/ledger_sync/adaptors/ledger_serializer_attribute_set.rb +1 -1
  17. data/lib/ledger_sync/adaptors/ledger_serializer_type/references_many_type.rb +1 -1
  18. data/lib/ledger_sync/adaptors/mixins/infer_adaptor_class_mixin.rb +24 -0
  19. data/lib/ledger_sync/adaptors/mixins/infer_ledger_serializer_mixin.rb +31 -0
  20. data/lib/ledger_sync/adaptors/mixins/infer_resource_class_mixin.rb +22 -0
  21. data/lib/ledger_sync/adaptors/mixins/offset_and_limit_pagination_searcher_mixin.rb +37 -0
  22. data/lib/ledger_sync/adaptors/netsuite/account/ledger_deserializer.rb +24 -0
  23. data/lib/ledger_sync/adaptors/netsuite/account/ledger_serializer.rb +22 -0
  24. data/lib/ledger_sync/adaptors/netsuite/account/operations/create.rb +28 -0
  25. data/lib/ledger_sync/adaptors/netsuite/account/operations/find.rb +28 -0
  26. data/lib/ledger_sync/adaptors/netsuite/account/searcher.rb +28 -0
  27. data/lib/ledger_sync/adaptors/netsuite/adaptor.rb +145 -0
  28. data/lib/ledger_sync/adaptors/netsuite/config.rb +6 -0
  29. data/lib/ledger_sync/adaptors/netsuite/currency/deledger_serializer.rb +28 -0
  30. data/lib/ledger_sync/adaptors/netsuite/currency/ledger_serializer.rb +25 -0
  31. data/lib/ledger_sync/adaptors/netsuite/currency/operations/create.rb +25 -0
  32. data/lib/ledger_sync/adaptors/netsuite/currency/operations/delete.rb +23 -0
  33. data/lib/ledger_sync/adaptors/netsuite/currency/operations/find.rb +23 -0
  34. data/lib/ledger_sync/adaptors/netsuite/currency/operations/update.rb +23 -0
  35. data/lib/ledger_sync/adaptors/netsuite/customer/ledger_deserializer.rb +27 -0
  36. data/lib/ledger_sync/adaptors/netsuite/customer/ledger_serializer.rb +38 -0
  37. data/lib/ledger_sync/adaptors/netsuite/customer/operations/create.rb +24 -0
  38. data/lib/ledger_sync/adaptors/netsuite/customer/operations/delete.rb +24 -0
  39. data/lib/ledger_sync/adaptors/netsuite/customer/operations/find.rb +24 -0
  40. data/lib/ledger_sync/adaptors/netsuite/customer/operations/update.rb +24 -0
  41. data/lib/ledger_sync/adaptors/netsuite/ledger_serializer.rb +30 -0
  42. data/lib/ledger_sync/adaptors/netsuite/ledger_serializer_type/reference_type.rb +24 -0
  43. data/lib/ledger_sync/adaptors/netsuite/ledger_serializer_type/subsidiary_type.rb +22 -0
  44. data/lib/ledger_sync/adaptors/netsuite/operation.rb +25 -0
  45. data/lib/ledger_sync/adaptors/netsuite/operation/create.rb +65 -0
  46. data/lib/ledger_sync/adaptors/netsuite/operation/delete.rb +49 -0
  47. data/lib/ledger_sync/adaptors/netsuite/operation/find.rb +56 -0
  48. data/lib/ledger_sync/adaptors/netsuite/operation/update.rb +68 -0
  49. data/lib/ledger_sync/adaptors/netsuite/record/http_method.rb +38 -0
  50. data/lib/ledger_sync/adaptors/netsuite/record/metadata.rb +75 -0
  51. data/lib/ledger_sync/adaptors/netsuite/record/property.rb +45 -0
  52. data/lib/ledger_sync/adaptors/netsuite/searcher.rb +17 -0
  53. data/lib/ledger_sync/adaptors/netsuite/token.rb +162 -0
  54. data/lib/ledger_sync/adaptors/netsuite/vendor/ledger_deserializer.rb +32 -0
  55. data/lib/ledger_sync/adaptors/netsuite/vendor/ledger_serializer.rb +35 -0
  56. data/lib/ledger_sync/adaptors/netsuite/vendor/operations/create.rb +27 -0
  57. data/lib/ledger_sync/adaptors/netsuite/vendor/operations/delete.rb +27 -0
  58. data/lib/ledger_sync/adaptors/netsuite/vendor/operations/find.rb +27 -0
  59. data/lib/ledger_sync/adaptors/netsuite/vendor/operations/update.rb +27 -0
  60. data/lib/ledger_sync/adaptors/netsuite_soap/adaptor.rb +92 -0
  61. data/lib/ledger_sync/adaptors/netsuite_soap/config.rb +5 -0
  62. data/lib/ledger_sync/adaptors/netsuite_soap/customer/ledger_serializer.rb +13 -0
  63. data/lib/ledger_sync/adaptors/netsuite_soap/customer/operations/create.rb +64 -0
  64. data/lib/ledger_sync/adaptors/netsuite_soap/customer/operations/find.rb +49 -0
  65. data/lib/ledger_sync/adaptors/netsuite_soap/ledger_serializer.rb +25 -0
  66. data/lib/ledger_sync/adaptors/netsuite_soap/operation.rb +40 -0
  67. data/lib/ledger_sync/adaptors/netsuite_soap/operation/create.rb +29 -0
  68. data/lib/ledger_sync/adaptors/netsuite_soap/operation/find.rb +15 -0
  69. data/lib/ledger_sync/adaptors/netsuite_soap/subsidiary/operations/create.rb +42 -0
  70. data/lib/ledger_sync/adaptors/netsuite_soap/subsidiary/operations/find.rb +38 -0
  71. data/lib/ledger_sync/adaptors/operation.rb +7 -11
  72. data/lib/ledger_sync/adaptors/quickbooks_online/account/searcher.rb +2 -13
  73. data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +158 -109
  74. data/lib/ledger_sync/adaptors/quickbooks_online/bill/searcher.rb +1 -15
  75. data/lib/ledger_sync/adaptors/quickbooks_online/config.rb +3 -2
  76. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +1 -0
  77. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +1 -0
  78. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +1 -0
  79. data/lib/ledger_sync/adaptors/quickbooks_online/customer/searcher.rb +2 -16
  80. data/lib/ledger_sync/adaptors/quickbooks_online/dashboard_url_helper.rb +57 -0
  81. data/lib/ledger_sync/adaptors/quickbooks_online/department/ledger_serializer.rb +38 -0
  82. data/lib/ledger_sync/adaptors/quickbooks_online/department/operations/create.rb +23 -0
  83. data/lib/ledger_sync/adaptors/quickbooks_online/department/operations/find.rb +23 -0
  84. data/lib/ledger_sync/adaptors/quickbooks_online/department/operations/update.rb +25 -0
  85. data/lib/ledger_sync/adaptors/quickbooks_online/department/searcher.rb +17 -0
  86. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/ledger_serializer.rb +3 -0
  87. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/create.rb +1 -0
  88. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/find.rb +1 -0
  89. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/update.rb +1 -0
  90. data/lib/ledger_sync/adaptors/quickbooks_online/deposit/searcher.rb +0 -15
  91. data/lib/ledger_sync/adaptors/quickbooks_online/expense/ledger_serializer.rb +0 -2
  92. data/lib/ledger_sync/adaptors/quickbooks_online/expense/searcher.rb +1 -15
  93. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/ledger_serializer.rb +35 -0
  94. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/create.rb +27 -0
  95. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/find.rb +25 -0
  96. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/update.rb +25 -0
  97. data/lib/ledger_sync/adaptors/quickbooks_online/invoice_sales_line_item/ledger_serializer.rb +30 -0
  98. data/lib/ledger_sync/adaptors/quickbooks_online/item/ledger_serializer.rb +13 -0
  99. data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/searcher.rb +1 -15
  100. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_class/ledger_serializer.rb +25 -0
  101. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_class/operations/create.rb +23 -0
  102. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_class/operations/find.rb +23 -0
  103. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_class/operations/update.rb +25 -0
  104. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_class/searcher.rb +15 -0
  105. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer.rb +8 -5
  106. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/entity_reference_type.rb +4 -14
  107. data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/transaction_reference_type.rb +49 -0
  108. data/lib/ledger_sync/adaptors/quickbooks_online/oauth_client.rb +93 -0
  109. data/lib/ledger_sync/adaptors/quickbooks_online/operation.rb +42 -7
  110. data/lib/ledger_sync/adaptors/quickbooks_online/operation/create.rb +5 -8
  111. data/lib/ledger_sync/adaptors/quickbooks_online/operation/find.rb +9 -9
  112. data/lib/ledger_sync/adaptors/quickbooks_online/operation/full_update.rb +17 -15
  113. data/lib/ledger_sync/adaptors/quickbooks_online/payment/ledger_serializer.rb +25 -0
  114. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +9 -6
  115. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +9 -2
  116. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +8 -1
  117. data/lib/ledger_sync/adaptors/quickbooks_online/payment_line_item/ledger_serializer.rb +19 -0
  118. data/lib/ledger_sync/adaptors/quickbooks_online/request.rb +98 -0
  119. data/lib/ledger_sync/adaptors/quickbooks_online/searcher.rb +29 -13
  120. data/lib/ledger_sync/adaptors/quickbooks_online/util/operation_error_parser.rb +1 -1
  121. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/create.rb +3 -0
  122. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/find.rb +3 -0
  123. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/update.rb +3 -0
  124. data/lib/ledger_sync/adaptors/quickbooks_online/vendor/searcher.rb +5 -54
  125. data/lib/ledger_sync/adaptors/quickbooks_online/webhook.rb +58 -0
  126. data/lib/ledger_sync/adaptors/quickbooks_online/webhook_event.rb +79 -0
  127. data/lib/ledger_sync/adaptors/quickbooks_online/webhook_notification.rb +42 -0
  128. data/lib/ledger_sync/adaptors/request.rb +53 -0
  129. data/lib/ledger_sync/adaptors/response.rb +55 -0
  130. data/lib/ledger_sync/adaptors/searcher.rb +3 -1
  131. data/lib/ledger_sync/adaptors/stripe/adaptor.rb +45 -0
  132. data/lib/ledger_sync/adaptors/stripe/config.rb +6 -0
  133. data/lib/ledger_sync/adaptors/stripe/customer/operations/create.rb +44 -0
  134. data/lib/ledger_sync/adaptors/stripe/customer/operations/delete.rb +35 -0
  135. data/lib/ledger_sync/adaptors/stripe/customer/operations/find.rb +44 -0
  136. data/lib/ledger_sync/adaptors/stripe/customer/operations/update.rb +43 -0
  137. data/lib/ledger_sync/adaptors/stripe/operation.rb +35 -0
  138. data/lib/ledger_sync/adaptors/stripe/operation/create.rb +17 -0
  139. data/lib/ledger_sync/adaptors/stripe/operation/delete.rb +17 -0
  140. data/lib/ledger_sync/adaptors/stripe/operation/find.rb +15 -0
  141. data/lib/ledger_sync/adaptors/stripe/operation/update.rb +17 -0
  142. data/lib/ledger_sync/adaptors/test/config.rb +0 -1
  143. data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +1 -0
  144. data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +1 -0
  145. data/lib/ledger_sync/adaptors/test/customer/operations/invalid.rb +1 -0
  146. data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +1 -0
  147. data/lib/ledger_sync/adaptors/test/customer/operations/valid.rb +1 -0
  148. data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +8 -1
  149. data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +9 -2
  150. data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +9 -5
  151. data/lib/ledger_sync/adaptors/test/vendor/operations/create.rb +5 -0
  152. data/lib/ledger_sync/adaptors/test/vendor/operations/find.rb +3 -0
  153. data/lib/ledger_sync/adaptors/test/vendor/operations/invalid.rb +5 -0
  154. data/lib/ledger_sync/adaptors/test/vendor/operations/update.rb +5 -0
  155. data/lib/ledger_sync/adaptors/test/vendor/operations/valid.rb +5 -0
  156. data/lib/ledger_sync/error/adaptor_errors.rb +18 -5
  157. data/lib/ledger_sync/error/operation_errors.rb +13 -4
  158. data/lib/ledger_sync/resource.rb +6 -0
  159. data/lib/ledger_sync/resource_attribute/dirty_mixin.rb +16 -15
  160. data/lib/ledger_sync/resources/bill.rb +7 -1
  161. data/lib/ledger_sync/resources/bill_line_item.rb +2 -0
  162. data/lib/ledger_sync/resources/currency.rb +9 -0
  163. data/lib/ledger_sync/resources/customer.rb +16 -0
  164. data/lib/ledger_sync/resources/department.rb +14 -0
  165. data/lib/ledger_sync/resources/deposit.rb +7 -0
  166. data/lib/ledger_sync/resources/deposit_line_item.rb +6 -0
  167. data/lib/ledger_sync/resources/expense.rb +5 -0
  168. data/lib/ledger_sync/resources/expense_line_item.rb +2 -0
  169. data/lib/ledger_sync/resources/invoice.rb +23 -0
  170. data/lib/ledger_sync/resources/invoice_sales_line_item.rb +17 -0
  171. data/lib/ledger_sync/resources/item.rb +5 -0
  172. data/lib/ledger_sync/resources/journal_entry.rb +5 -1
  173. data/lib/ledger_sync/resources/journal_entry_line_item.rb +4 -0
  174. data/lib/ledger_sync/resources/ledger_class.rb +14 -0
  175. data/lib/ledger_sync/resources/payment.rb +13 -0
  176. data/lib/ledger_sync/resources/payment_line_item.rb +15 -0
  177. data/lib/ledger_sync/resources/subsidiary.rb +8 -0
  178. data/lib/ledger_sync/resources/transfer.rb +4 -0
  179. data/lib/ledger_sync/resources/vendor.rb +9 -2
  180. data/lib/ledger_sync/type/reference_many.rb +12 -1
  181. data/lib/ledger_sync/type/reference_one.rb +1 -1
  182. data/lib/ledger_sync/util/resonad.rb +18 -0
  183. data/lib/ledger_sync/util/signer.rb +36 -0
  184. data/lib/ledger_sync/util/string_helpers.rb +12 -12
  185. data/lib/ledger_sync/version.rb +1 -1
  186. data/qa/env_spec.rb +5 -0
  187. data/qa/netsuite/account_spec.rb +20 -0
  188. data/qa/netsuite/currency_spec.rb +16 -0
  189. data/qa/netsuite/customer.rb +76 -0
  190. data/qa/netsuite/customer_spec.rb +21 -0
  191. data/qa/netsuite/vendor.rb +76 -0
  192. data/qa/netsuite/vendor_spec.rb +23 -0
  193. data/qa/netsuite_soap/customer_spec.rb +21 -0
  194. data/qa/netsuite_soap/subsidiary_spec.rb +0 -0
  195. data/qa/netsuite_test.rb +42 -0
  196. data/qa/qa_helper.rb +58 -0
  197. data/qa/quickbooks_online/account_spec.rb +14 -0
  198. data/qa/quickbooks_online/customer_spec.rb +13 -0
  199. data/qa/quickbooks_online/expense_spec.rb +31 -0
  200. data/qa/quickbooks_online/vendor_spec.rb +13 -0
  201. data/qa/stripe/customers_spec.rb +15 -0
  202. data/qa/support/adaptor_helpers.rb +99 -0
  203. data/qa/support/adaptor_support_setup.rb +23 -0
  204. data/qa/support/netsuite_helpers.rb +33 -0
  205. data/qa/support/netsuite_shared_examples.rb +30 -0
  206. data/qa/support/netsuite_soap_helpers.rb +33 -0
  207. data/qa/support/netsuite_soap_shared_examples.rb +10 -0
  208. data/qa/support/quickbooks_online_helpers.rb +42 -0
  209. data/qa/support/quickbooks_online_shared_examples.rb +82 -0
  210. data/qa/support/shared_examples.rb +127 -0
  211. data/qa/support/stripe_helpers.rb +22 -0
  212. data/qa/support/stripe_shared_examples.rb +10 -0
  213. data/qa/test.rb +67 -0
  214. data/release.sh +13 -1
  215. metadata +189 -3
  216. data/qa.rb +0 -142
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'webhook_event'
4
+
5
+ # ref: https://developer.intuit.com/app/developer/qbo/docs/develop/webhooks/managing-webhooks-notifications#validating-the-notification
6
+ module LedgerSync
7
+ module Adaptors
8
+ module QuickBooksOnline
9
+ class Webhook
10
+ attr_reader :notifications,
11
+ :original_payload,
12
+ :payload
13
+
14
+ def initialize(payload:)
15
+ @original_payload = payload
16
+ @payload = payload.is_a?(String) ? JSON.parse(payload) : payload
17
+
18
+ event_notifications_payload = @payload.dig('eventNotifications')
19
+ raise 'Invalid payload: Could not find eventNotifications' unless event_notifications_payload.is_a?(Array)
20
+
21
+ @notifications = []
22
+
23
+ event_notifications_payload.each do |event_notification_payload|
24
+ @notifications << WebhookNotification.new(
25
+ payload: event_notification_payload,
26
+ webhook: self
27
+ )
28
+ end
29
+ end
30
+
31
+ def events
32
+ notifications.map(&:events)
33
+ end
34
+
35
+ def resources
36
+ @resources ||= notifications.map(&:resources).flatten.compact
37
+ end
38
+
39
+ def valid?(signature:, verification_token:)
40
+ self.class.valid?(
41
+ payload: payload.to_json,
42
+ signature: signature,
43
+ verification_token: verification_token
44
+ )
45
+ end
46
+
47
+ def self.valid?(payload:, signature:, verification_token:)
48
+ raise 'Cannot verify non-String payload' unless payload.is_a?(String)
49
+
50
+ digest = OpenSSL::Digest.new('sha256')
51
+ hmac = OpenSSL::HMAC.digest(digest, verification_token, payload)
52
+ base64 = Base64.encode64(hmac).strip
53
+ base64 == signature
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ # ref: https://developer.intuit.com/app/developer/qbo/docs/develop/webhooks/managing-webhooks-notifications#validating-the-notification
4
+ module LedgerSync
5
+ module Adaptors
6
+ module QuickBooksOnline
7
+ class WebhookEvent
8
+ attr_reader :deleted_id,
9
+ :event_operation,
10
+ :last_updated_at,
11
+ :ledger_id,
12
+ :original_payload,
13
+ :payload,
14
+ :quickbooks_online_resource_type,
15
+ :webhook_notification,
16
+ :webhook
17
+
18
+ def initialize(payload:, webhook_notification: nil)
19
+ @original_payload = payload
20
+ @payload = payload.is_a?(String) ? JSON.parse(payload) : payload
21
+
22
+ @deleted_id = @payload.dig('deletedId')
23
+
24
+ @event_operation = @payload.dig('operation')
25
+ raise 'Invalid payload: Could not find operation' if @event_operation.blank?
26
+
27
+ @last_updated_at = @payload.dig('lastUpdated')
28
+ raise 'Invalid payload: Could not find lastUpdated' if @last_updated_at.blank?
29
+
30
+ @last_updated_at = Time.parse(@last_updated_at)
31
+
32
+ @ledger_id = @payload.dig('id')
33
+ raise 'Invalid payload: Could not find id' if @ledger_id.blank?
34
+
35
+ @quickbooks_online_resource_type = @payload.dig('name')
36
+ raise 'Invalid payload: Could not find name' if @quickbooks_online_resource_type.blank?
37
+
38
+ @webhook_notification = webhook_notification
39
+ @webhook = webhook_notification.try(:webhook)
40
+ end
41
+
42
+ def find(adaptor:)
43
+ find_operation(adaptor: adaptor).perform
44
+ end
45
+
46
+ def find_operation(adaptor:)
47
+ find_operation_class(adaptor: adaptor).new(
48
+ adaptor: adaptor,
49
+ resource: resource_class.new(ledger_id: ledger_id)
50
+ )
51
+ end
52
+
53
+ def find_operation_class(adaptor:)
54
+ adaptor.class.base_operation_module_for(resource_class: resource_class)::Find
55
+ end
56
+
57
+ def local_resource_type
58
+ @local_resource_type ||= resource_class.resource_type
59
+ end
60
+
61
+ def resource
62
+ return unless resource_class.present?
63
+
64
+ resource_class.new(ledger_id: ledger_id)
65
+ end
66
+
67
+ def resource!
68
+ raise "Resource class does not exist for QuickBooks Online object: #{quickbooks_online_resource_type}" if resource.nil?
69
+
70
+ resource
71
+ end
72
+
73
+ def resource_class
74
+ @resource_class ||= Adaptor.resource_from_ledger_type(type: quickbooks_online_resource_type.downcase)
75
+ end
76
+ end
77
+ end
78
+ end
79
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'webhook_event'
4
+
5
+ # ref: https://developer.intuit.com/app/developer/qbo/docs/develop/webhooks/managing-webhooks-notifications#validating-the-notification
6
+ module LedgerSync
7
+ module Adaptors
8
+ module QuickBooksOnline
9
+ class WebhookNotification
10
+ attr_reader :events,
11
+ :original_payload,
12
+ :payload,
13
+ :realm_id,
14
+ :webhook
15
+
16
+ def initialize(payload:, webhook: nil)
17
+ @original_payload = payload
18
+ @payload = payload.is_a?(String) ? JSON.parse(payload) : payload
19
+
20
+ @realm_id = @payload.dig('realmId')
21
+ raise 'Invalid payload: Could not find realmId' if @realm_id.blank?
22
+
23
+ events_payload = @payload.dig('dataChangeEvent', 'entities')
24
+ raise 'Invalid payload: Could not find dataChangeEvent -> entities' unless events_payload.is_a?(Array)
25
+
26
+ @events = []
27
+
28
+ events_payload.each do |event_payload|
29
+ @events << WebhookEvent.new(
30
+ payload: event_payload,
31
+ webhook_notification: self
32
+ )
33
+ end
34
+ end
35
+
36
+ def resources
37
+ @resources ||= events.map(&:resource).compact
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,53 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LedgerSync
4
+ module Adaptors
5
+ class Request
6
+ attr_reader :body,
7
+ :headers,
8
+ :method,
9
+ :response,
10
+ :url
11
+
12
+ def initialize(body: nil, headers: {}, method: nil, url: nil)
13
+ @body = body
14
+ @headers = headers
15
+ @method = method
16
+ @url = url
17
+ end
18
+
19
+ def perform
20
+ raise 'Request already performed' if performed?
21
+
22
+ faraday_response = Faraday.send(method, url) do |req|
23
+ req.headers = headers
24
+ req.body = body.to_json unless body.nil?
25
+ end
26
+
27
+ @response = Response.new_from_faraday_response(faraday_response: faraday_response, request: self)
28
+ @performed = true
29
+ @response
30
+ end
31
+
32
+ def performed?
33
+ @performed == true
34
+ end
35
+
36
+ def self.delete(**keywords)
37
+ new(keywords.merge(method: :delete))
38
+ end
39
+
40
+ def self.get(**keywords)
41
+ new(keywords.merge(method: :get))
42
+ end
43
+
44
+ def self.post(**keywords)
45
+ new(keywords.merge(method: :post))
46
+ end
47
+
48
+ def self.put(**keywords)
49
+ new(keywords.merge(method: :put))
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,55 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ class Response
4
+ attr_reader :body,
5
+ :headers,
6
+ :raw,
7
+ :request,
8
+ :status
9
+
10
+ def initialize(body: nil, headers: {}, raw: nil, request:, status:)
11
+ @body = parse_json(body)
12
+ @headers = headers
13
+ @raw = raw
14
+ @request = request
15
+ @status = status
16
+ end
17
+
18
+ def failure?
19
+ !success?
20
+ end
21
+
22
+ def success?
23
+ (200..299).include?(status)
24
+ end
25
+
26
+ def self.new_from_faraday_response(faraday_response:, request:)
27
+ new(
28
+ body: faraday_response.body,
29
+ headers: faraday_response.headers,
30
+ raw: faraday_response,
31
+ request: request,
32
+ status: faraday_response.status
33
+ )
34
+ end
35
+
36
+ def self.new_from_oauth_response(oauth_response:, request:)
37
+ # Uses the same API
38
+ new_from_faraday_response(
39
+ faraday_response: oauth_response,
40
+ request: request
41
+ )
42
+ end
43
+
44
+ private
45
+
46
+ def parse_json(json)
47
+ return if json.nil?
48
+
49
+ JSON.parse(json)
50
+ rescue JSON::ParserError
51
+ nil
52
+ end
53
+ end
54
+ end
55
+ end
@@ -4,11 +4,13 @@ module LedgerSync
4
4
  module Adaptors
5
5
  class Searcher
6
6
  include SimplySerializable::Mixin
7
+ include Mixins::InferResourceClassMixin
8
+ include Mixins::InferLedgerSerializerMixin
7
9
 
8
10
  attr_reader :adaptor,
9
11
  :query,
10
12
  :pagination,
11
- :resources
13
+ :request
12
14
 
13
15
  serialize only: %i[
14
16
  adaptor
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ require 'oauth2'
4
+
5
+ module LedgerSync
6
+ module Adaptors
7
+ module Stripe
8
+ class Adaptor < LedgerSync::Adaptors::Adaptor
9
+ attr_reader :api_key
10
+
11
+ def initialize(
12
+ api_key:
13
+ )
14
+ @api_key = api_key
15
+ end
16
+
17
+ def url_for(resource:)
18
+ base_url = 'https://dashboard.stripe.com'
19
+ resource_path = case resource
20
+ when LedgerSync::Customer
21
+ "/customers/#{resource.ledger_id}"
22
+ else
23
+ raise Error::AdaptorError::UnknownURLFormat.new(
24
+ adaptor: self,
25
+ resource: resource
26
+ )
27
+ end
28
+
29
+ base_url + resource_path
30
+ end
31
+
32
+ def wrap_perform
33
+ ::Stripe.api_key = api_key
34
+ yield
35
+ ensure
36
+ ::Stripe.api_key = nil
37
+ end
38
+
39
+ def self.ledger_attributes_to_save
40
+ []
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ LedgerSync.register_adaptor(:stripe) do |config|
4
+ config.name = 'Stripe'
5
+ config.rate_limiting_wait_in_seconds = 60
6
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LedgerSync
4
+ module Adaptors
5
+ module Stripe
6
+ module Customer
7
+ module Operations
8
+ class Create < Stripe::Operation::Create
9
+ class Contract < LedgerSync::Adaptors::Contract
10
+ params do
11
+ required(:external_id).maybe(:string)
12
+ required(:ledger_id).value(:nil)
13
+ required(:email).maybe(:string)
14
+ required(:name).filled(:string)
15
+ required(:phone_number).maybe(:string)
16
+ optional(:subsidiary).maybe(:hash, Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ stripe_customer = ::Stripe::Customer.create(
24
+ email: resource.email,
25
+ metadata: {
26
+ external_id: resource.external_id
27
+ },
28
+ name: resource.name,
29
+ phone: resource.phone_number
30
+ )
31
+
32
+ resource.ledger_id = stripe_customer.id
33
+
34
+ success(
35
+ resource: resource,
36
+ response: stripe_customer
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,35 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LedgerSync
4
+ module Adaptors
5
+ module Stripe
6
+ module Customer
7
+ module Operations
8
+ class Delete < Stripe::Operation::Delete
9
+ class Contract < LedgerSync::Adaptors::Contract
10
+ params do
11
+ required(:external_id).maybe(:string)
12
+ required(:ledger_id).filled(:string)
13
+ required(:email).maybe(:string)
14
+ required(:name).maybe(:string)
15
+ required(:phone_number).maybe(:string)
16
+ optional(:subsidiary).maybe(:hash, Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ stripe_customer = ::Stripe::Customer.delete(resource.ledger_id)
24
+
25
+ success(
26
+ resource: resource,
27
+ response: stripe_customer
28
+ )
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,44 @@
1
+ # frozen_string_literal: true
2
+
3
+ module LedgerSync
4
+ module Adaptors
5
+ module Stripe
6
+ module Customer
7
+ module Operations
8
+ class Find < Stripe::Operation::Find
9
+ class Contract < LedgerSync::Adaptors::Contract
10
+ params do
11
+ required(:external_id).maybe(:string)
12
+ required(:ledger_id).filled(:string)
13
+ optional(:email).maybe(:string)
14
+ optional(:name).maybe(:string)
15
+ optional(:phone_number).maybe(:string)
16
+ optional(:subsidiary).maybe(:hash, Types::Reference)
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def operate
23
+ stripe_customer = ::Stripe::Customer.retrieve(
24
+ resource.ledger_id
25
+ )
26
+
27
+ resource.external_id = stripe_customer.metadata['external_id']
28
+ resource.email = stripe_customer.email
29
+ resource.name = stripe_customer.name
30
+ resource.phone_number = stripe_customer.phone
31
+
32
+ resource.ledger_id = stripe_customer.id
33
+
34
+ success(
35
+ resource: resource,
36
+ response: stripe_customer
37
+ )
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end