ledger_sync 0.1.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.coveralls.yml +1 -0
- data/.github/ISSUE_TEMPLATE/bug_report.md +38 -0
- data/.github/ISSUE_TEMPLATE/feature_request.md +20 -0
- data/.gitignore +4 -0
- data/.rubocop.yml +4 -0
- data/.rubocop_todo.yml +25 -0
- data/.travis.yml +1 -1
- data/Dockerfile +8 -0
- data/Gemfile +3 -1
- data/Gemfile.lock +137 -8
- data/README.md +184 -9
- data/Rakefile +3 -3
- data/bin/console +3 -3
- data/docker-compose.yml +4 -0
- data/ledger_sync.gemspec +32 -11
- data/lib/ledger_sync.rb +115 -3
- data/lib/ledger_sync/adaptor_configuration.rb +55 -0
- data/lib/ledger_sync/adaptor_configuration_store.rb +52 -0
- data/lib/ledger_sync/adaptors/adaptor.rb +66 -0
- data/lib/ledger_sync/adaptors/contract.rb +16 -0
- data/lib/ledger_sync/adaptors/operation.rb +213 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +161 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/config.rb +7 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +44 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +35 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +53 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/upsert.rb +42 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/searcher.rb +63 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/create.rb +63 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/find.rb +36 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/update.rb +67 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/invoice/operations/upsert.rb +44 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +64 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +35 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +64 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/upsert.rb +53 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/create.rb +46 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/find.rb +34 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/update.rb +50 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/product/operations/upsert.rb +43 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/util/adaptor_error_parser.rb +102 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/util/error_matcher.rb +54 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/util/error_parser.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/util/operation_error_parser.rb +96 -0
- data/lib/ledger_sync/adaptors/searcher.rb +64 -0
- data/lib/ledger_sync/adaptors/test/adaptor.rb +47 -0
- data/lib/ledger_sync/adaptors/test/config.rb +7 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +49 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +35 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/invalid.rb +20 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +46 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/upsert.rb +42 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/valid.rb +26 -0
- data/lib/ledger_sync/adaptors/test/customer/searcher.rb +40 -0
- data/lib/ledger_sync/adaptors/test/error/adaptor_error/operations/throttle_error.rb +28 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +56 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +35 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +62 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/upsert.rb +53 -0
- data/lib/ledger_sync/concerns/validatable.rb +19 -0
- data/lib/ledger_sync/core_ext/resonad.rb +16 -0
- data/lib/ledger_sync/error.rb +10 -0
- data/lib/ledger_sync/error/adaptor_errors.rb +47 -0
- data/lib/ledger_sync/error/operation_errors.rb +41 -0
- data/lib/ledger_sync/error/resource_errors.rb +20 -0
- data/lib/ledger_sync/resource.rb +92 -0
- data/lib/ledger_sync/resources/customer.rb +8 -0
- data/lib/ledger_sync/resources/invoice.rb +12 -0
- data/lib/ledger_sync/resources/payment.rb +11 -0
- data/lib/ledger_sync/resources/product.rb +6 -0
- data/lib/ledger_sync/resources/vendor.rb +6 -0
- data/lib/ledger_sync/result.rb +140 -0
- data/lib/ledger_sync/sync.rb +107 -0
- data/lib/ledger_sync/util/coordinator.rb +72 -0
- data/lib/ledger_sync/util/debug.rb +16 -0
- data/lib/ledger_sync/util/hash_helpers.rb +13 -0
- data/lib/ledger_sync/util/performer.rb +29 -0
- data/lib/ledger_sync/util/resources_builder.rb +68 -0
- data/lib/ledger_sync/util/string_helpers.rb +37 -0
- data/lib/ledger_sync/util/validator.rb +49 -0
- data/lib/ledger_sync/version.rb +1 -1
- data/release.sh +8 -0
- metadata +334 -11
- 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
|