ledger_sync 0.1.0 → 1.0.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.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
  4. data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
  5. data/.gitignore +4 -0
  6. data/.rubocop.yml +4 -0
  7. data/.rubocop_todo.yml +25 -0
  8. data/.travis.yml +1 -1
  9. data/Dockerfile +8 -0
  10. data/Gemfile +3 -1
  11. data/Gemfile.lock +137 -8
  12. data/README.md +184 -9
  13. data/Rakefile +3 -3
  14. data/bin/console +3 -3
  15. data/docker-compose.yml +4 -0
  16. data/ledger_sync.gemspec +32 -11
  17. data/lib/ledger_sync.rb +115 -3
  18. data/lib/ledger_sync/adaptor_configuration.rb +55 -0
  19. data/lib/ledger_sync/adaptor_configuration_store.rb +52 -0
  20. data/lib/ledger_sync/adaptors/adaptor.rb +66 -0
  21. data/lib/ledger_sync/adaptors/contract.rb +16 -0
  22. data/lib/ledger_sync/adaptors/operation.rb +213 -0
  23. data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +161 -0
  24. data/lib/ledger_sync/adaptors/quickbooks_online/config.rb +7 -0
  25. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +44 -0
  26. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +35 -0
  27. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +53 -0
  28. data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/upsert.rb +42 -0
  29. data/lib/ledger_sync/adaptors/quickbooks_online/customer/searcher.rb +63 -0
  30. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/create.rb +63 -0
  31. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/find.rb +36 -0
  32. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/update.rb +67 -0
  33. data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/upsert.rb +44 -0
  34. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +64 -0
  35. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +35 -0
  36. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +64 -0
  37. data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/upsert.rb +53 -0
  38. data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/create.rb +46 -0
  39. data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/find.rb +34 -0
  40. data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/update.rb +50 -0
  41. data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/upsert.rb +43 -0
  42. data/lib/ledger_sync/adaptors/quickbooks_online/util/adaptor_error_parser.rb +102 -0
  43. data/lib/ledger_sync/adaptors/quickbooks_online/util/error_matcher.rb +54 -0
  44. data/lib/ledger_sync/adaptors/quickbooks_online/util/error_parser.rb +27 -0
  45. data/lib/ledger_sync/adaptors/quickbooks_online/util/operation_error_parser.rb +96 -0
  46. data/lib/ledger_sync/adaptors/searcher.rb +64 -0
  47. data/lib/ledger_sync/adaptors/test/adaptor.rb +47 -0
  48. data/lib/ledger_sync/adaptors/test/config.rb +7 -0
  49. data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +49 -0
  50. data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +35 -0
  51. data/lib/ledger_sync/adaptors/test/customer/operations/invalid.rb +20 -0
  52. data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +46 -0
  53. data/lib/ledger_sync/adaptors/test/customer/operations/upsert.rb +42 -0
  54. data/lib/ledger_sync/adaptors/test/customer/operations/valid.rb +26 -0
  55. data/lib/ledger_sync/adaptors/test/customer/searcher.rb +40 -0
  56. data/lib/ledger_sync/adaptors/test/error/adaptor_error/operations/throttle_error.rb +28 -0
  57. data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +56 -0
  58. data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +35 -0
  59. data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +62 -0
  60. data/lib/ledger_sync/adaptors/test/payment/operations/upsert.rb +53 -0
  61. data/lib/ledger_sync/concerns/validatable.rb +19 -0
  62. data/lib/ledger_sync/core_ext/resonad.rb +16 -0
  63. data/lib/ledger_sync/error.rb +10 -0
  64. data/lib/ledger_sync/error/adaptor_errors.rb +47 -0
  65. data/lib/ledger_sync/error/operation_errors.rb +41 -0
  66. data/lib/ledger_sync/error/resource_errors.rb +20 -0
  67. data/lib/ledger_sync/resource.rb +92 -0
  68. data/lib/ledger_sync/resources/customer.rb +8 -0
  69. data/lib/ledger_sync/resources/invoice.rb +12 -0
  70. data/lib/ledger_sync/resources/payment.rb +11 -0
  71. data/lib/ledger_sync/resources/product.rb +6 -0
  72. data/lib/ledger_sync/resources/vendor.rb +6 -0
  73. data/lib/ledger_sync/result.rb +140 -0
  74. data/lib/ledger_sync/sync.rb +107 -0
  75. data/lib/ledger_sync/util/coordinator.rb +72 -0
  76. data/lib/ledger_sync/util/debug.rb +16 -0
  77. data/lib/ledger_sync/util/hash_helpers.rb +13 -0
  78. data/lib/ledger_sync/util/performer.rb +29 -0
  79. data/lib/ledger_sync/util/resources_builder.rb +68 -0
  80. data/lib/ledger_sync/util/string_helpers.rb +37 -0
  81. data/lib/ledger_sync/util/validator.rb +49 -0
  82. data/lib/ledger_sync/version.rb +1 -1
  83. data/release.sh +8 -0
  84. metadata +334 -11
  85. data/.rspec +0 -3
@@ -0,0 +1,36 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Invoice
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(:currency).maybe(:string)
11
+ required(:customer).maybe(Types::Reference)
12
+ required(:line_items).maybe(:array)
13
+ required(:number).maybe(:integer)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def operate
20
+ return failure(nil) if resource.ledger_id.nil?
21
+
22
+ response = adaptor.find(
23
+ resource: 'invoice',
24
+ id: resource.ledger_id
25
+ )
26
+
27
+ success(response: response)
28
+ rescue OAuth2::Error => e
29
+ failure(e)
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,67 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Invoice
5
+ module Operations
6
+ class Update < Operation::Update
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ params do
9
+ required(:ledger_id).filled(:string)
10
+ required(:currency).filled(:string)
11
+ required(:customer).filled(Types::Reference)
12
+ required(:line_items).maybe(:array)
13
+ required(:number).maybe(:integer)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def operate
20
+ ledger_resource_data = adaptor.find(
21
+ resource: 'payment',
22
+ id: resource.ledger_id
23
+ )
24
+
25
+ response = adaptor.upsert(
26
+ resource: 'payment',
27
+ payload: merge_into(from: local_resource_data, to: ledger_resource_data)
28
+ )
29
+
30
+ resource.ledger_id = response.dig('Id')
31
+ success(response: response)
32
+ rescue OAuth2::Error => e
33
+ failure(e)
34
+ end
35
+
36
+ def local_resource_data
37
+ {
38
+ 'CurrencyRef': {
39
+ 'value': resource.currency,
40
+ },
41
+ 'CustomerRef': {
42
+ 'value': resource.customer,
43
+ },
44
+ 'DocNumber': resource.number,
45
+ 'Line': resource.line_items.each_with_index.map do |line, i|
46
+ {
47
+ 'LineNum': i,
48
+ 'Amount': line.fetch(:amount),
49
+ 'SalesItemLineDetail': {
50
+ 'TaxCodeRef': {
51
+ 'value': 'NON'
52
+ },
53
+ 'ItemRef': {
54
+ 'value': line.fetch(:product)
55
+ }
56
+ },
57
+ 'DetailType': 'SalesItemLineDetail'
58
+ }
59
+ end
60
+ }
61
+ end
62
+ end
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,44 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Invoice
5
+ module Operations
6
+ class Upsert < Operation::Upsert
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ schema do
9
+ required(:ledger_id).maybe(:string)
10
+ required(:currency).maybe(:string)
11
+ required(:customer).maybe(Types::Reference)
12
+ required(:line_items).maybe(:array)
13
+ required(:number).maybe(:integer)
14
+ end
15
+ end
16
+
17
+ private
18
+
19
+ def build
20
+ op = if qbo_invoice?
21
+ Update.new(adaptor: adaptor, resource: resource)
22
+ else
23
+ Create.new(adaptor: adaptor, resource: resource)
24
+ end
25
+
26
+ add_root_operation(op)
27
+ end
28
+
29
+ def find_result
30
+ @find_result ||= Find.new(
31
+ adaptor: adaptor,
32
+ resource: resource
33
+ ).perform
34
+ end
35
+
36
+ def qbo_invoice?
37
+ find_result.success?
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -0,0 +1,64 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Payment
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(:ledger_id).maybe(:string)
11
+ required(:amount).filled(:integer)
12
+ required(:currency).filled(:string)
13
+ required(:customer).hash do
14
+ required(:object).filled(:symbol)
15
+ required(:id).filled(:string)
16
+ end
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def build
23
+ build_customer_operation
24
+ add_root_operation(self)
25
+ end
26
+
27
+ def operate
28
+ response = adaptor.upsert(
29
+ resource: 'payment',
30
+ payload: local_resource_data
31
+ )
32
+
33
+ resource.ledger_id = response.dig('Id')
34
+ success(response: response)
35
+ rescue OAuth2::Error => e
36
+ failure(e)
37
+ end
38
+
39
+ def build_customer_operation
40
+ customer = Customer::Operations::Upsert.new(
41
+ adaptor: adaptor,
42
+ resource: resource.customer
43
+ )
44
+
45
+ add_before_operation(customer)
46
+ end
47
+
48
+ def local_resource_data
49
+ {
50
+ 'TotalAmt': resource.amount,
51
+ 'CurrencyRef': {
52
+ 'value': resource.currency,
53
+ },
54
+ 'CustomerRef': {
55
+ 'value': resource.customer.ledger_id,
56
+ }
57
+ }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,35 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Payment
5
+ module Operations
6
+ class Find < Operation::Find
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ schema do
9
+ required(:ledger_id).filled(:string)
10
+ optional(:amount).maybe(:integer)
11
+ optional(:currency).maybe(:string)
12
+ optional(:customer).maybe(Types::Reference)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def operate
19
+ return failure(nil) if resource.ledger_id.nil?
20
+
21
+ response = adaptor.find(
22
+ resource: 'payment',
23
+ id: resource.ledger_id
24
+ )
25
+
26
+ success(response: response)
27
+ rescue OAuth2::Error => e
28
+ failure(e)
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,64 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Payment
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(:amount).filled(:integer)
11
+ required(:currency).filled(:string)
12
+ required(:customer).hash(Types::Reference)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def build
19
+ build_customer_operation
20
+ add_root_operation(self)
21
+ end
22
+
23
+ def operate
24
+ ledger_resource_data = adaptor.find(
25
+ resource: 'payment',
26
+ id: resource.ledger_id
27
+ )
28
+ response = adaptor.upsert(
29
+ resource: 'payment',
30
+ payload: merge_into(from: local_resource_data, to: ledger_resource_data)
31
+ )
32
+
33
+ resource.ledger_id = response.dig('Id')
34
+ success(response: response)
35
+ rescue OAuth2::Error => e
36
+ failure(e)
37
+ end
38
+
39
+ def build_customer_operation
40
+ customer = Customer::Operations::Upsert.new(
41
+ adaptor: adaptor,
42
+ resource: resource.customer
43
+ )
44
+
45
+ add_before_operation(customer)
46
+ end
47
+
48
+ def local_resource_data
49
+ {
50
+ 'TotalAmt': resource.amount,
51
+ 'CurrencyRef': {
52
+ 'value': resource.currency,
53
+ },
54
+ 'CustomerRef': {
55
+ 'value': resource.customer.ledger_id,
56
+ }
57
+ }
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
@@ -0,0 +1,53 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Payment
5
+ module Operations
6
+ class Upsert < Operation::Upsert
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ schema do
9
+ required(:ledger_id).maybe(:string)
10
+ required(:amount).filled(:integer)
11
+ required(:currency).filled(:string)
12
+ required(:customer).hash(Types::Reference)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def build
19
+ op = if qbo_payment?
20
+ Update.new(adaptor: adaptor, resource: resource)
21
+ else
22
+ Create.new(adaptor: adaptor, resource: resource)
23
+ end
24
+
25
+ build_customer_operation
26
+ add_root_operation(op)
27
+ end
28
+
29
+ def build_customer_operation
30
+ customer = Customer::Operations::Upsert.new(
31
+ adaptor: adaptor,
32
+ resource: resource.customer
33
+ )
34
+
35
+ add_before_operation(customer)
36
+ end
37
+
38
+ def find_result
39
+ @find_result ||= Find.new(
40
+ adaptor: adaptor,
41
+ resource: resource
42
+ ).perform
43
+ end
44
+
45
+ def qbo_payment?
46
+ find_result.success?
47
+ end
48
+ end
49
+ end
50
+ end
51
+ end
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Product
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(:ledger_id).value(:nil)
11
+ required(:name).filled(:string)
12
+ optional(:description).maybe(:string)
13
+ end
14
+ end
15
+
16
+ private
17
+
18
+ def operate
19
+ response = adaptor.upsert(
20
+ resource: 'item',
21
+ payload: local_resource_data
22
+ )
23
+
24
+ resource.ledger_id = response.dig('Id')
25
+ success(response: response)
26
+ rescue OAuth2::Error => e
27
+ failure(e)
28
+ end
29
+
30
+ def local_resource_data
31
+ {
32
+ 'Name': resource.name,
33
+ 'Description': resource.description,
34
+ 'Type': 'Service',
35
+ 'IncomeAccountRef': {
36
+ 'value': '1',
37
+ 'name': 'Services'
38
+ }
39
+ }
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,34 @@
1
+ module LedgerSync
2
+ module Adaptors
3
+ module QuickBooksOnline
4
+ module Product
5
+ module Operations
6
+ class Find < Operation::Find
7
+ class Contract < LedgerSync::Adaptors::Contract
8
+ params do
9
+ required(:ledger_id).filled(:string)
10
+ optional(:description).maybe(:string)
11
+ optional(:name).maybe(:string)
12
+ end
13
+ end
14
+
15
+ private
16
+
17
+ def operate
18
+ return failure(nil) if resource.ledger_id.nil?
19
+
20
+ response = @adaptor.find(
21
+ resource: 'item',
22
+ id: resource.ledger_id
23
+ )
24
+
25
+ success(response: response)
26
+ rescue OAuth2::Error => e
27
+ failure(e)
28
+ end
29
+ end
30
+ end
31
+ end
32
+ end
33
+ end
34
+ end