ledger_sync 1.1.2 → 1.1.3
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.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit_line_item/ledger_serializer.rb +4 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/ledger_serializer.rb +3 -2
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/create.rb +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/find.rb +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/update.rb +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer.rb +33 -8
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/amount_type.rb +1 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/entity_reference_type.rb +59 -0
- data/lib/ledger_sync/adaptors/test/expense/operations/create.rb +1 -31
- data/lib/ledger_sync/adaptors/test/expense/operations/find.rb +1 -1
- data/lib/ledger_sync/adaptors/test/expense/operations/update.rb +1 -1
- data/lib/ledger_sync/resources/deposit_line_item.rb +2 -0
- data/lib/ledger_sync/resources/expense.rb +3 -1
- data/lib/ledger_sync/type/reference_one.rb +16 -2
- data/lib/ledger_sync/util/resources_builder.rb +19 -1
- data/lib/ledger_sync/version.rb +1 -1
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 0e39d8dc0e6f3df94374cb5200d7062213327b06f470111c9d3baf4fe7407e76
|
4
|
+
data.tar.gz: 206ccec75be3d425dbaf6b3567af57536cab77851e8c815c31ee1642b81cb0ef
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1024346df20614497f7db8e000bacd9440efb24084e2675769295ef69dc2d1d6c1770d8c5f25258ad05ba1b7bdb6d9ae23440c8d56787c3980c572e65a2af52a
|
7
|
+
data.tar.gz: b5571c6836c32ade58704aae76ac4b1577c5f457240c5ce2ef121a27b9424eb46619366fe09650c4a6953e44d6dd5b9df1eba4e42d8d313e72b17433e26075cd
|
data/Gemfile.lock
CHANGED
@@ -108,7 +108,7 @@ module LedgerSync
|
|
108
108
|
end
|
109
109
|
|
110
110
|
def url_for(resource:)
|
111
|
-
base_url = test ? 'https://app.sandbox.qbo.intuit.com/app' : 'https://
|
111
|
+
base_url = test ? 'https://app.sandbox.qbo.intuit.com/app' : 'https://qbo.intuit.com/app'
|
112
112
|
resource_path = case resource
|
113
113
|
when LedgerSync::Account
|
114
114
|
"/register?accountId=#{resource.ledger_id}"
|
@@ -14,6 +14,10 @@ module LedgerSync
|
|
14
14
|
attribute ledger_attribute: 'DepositLineDetail.AccountRef.value',
|
15
15
|
resource_attribute: 'account.ledger_id'
|
16
16
|
|
17
|
+
attribute ledger_attribute: 'DepositLineDetail.Entity',
|
18
|
+
resource_attribute: :entity,
|
19
|
+
type: LedgerSerializerType::EntityReferenceType
|
20
|
+
|
17
21
|
attribute ledger_attribute: 'Amount',
|
18
22
|
resource_attribute: :amount,
|
19
23
|
type: LedgerSerializerType::AmountType
|
@@ -29,8 +29,9 @@ module LedgerSync
|
|
29
29
|
attribute ledger_attribute: 'ExchangeRate',
|
30
30
|
resource_attribute: :exchange_rate
|
31
31
|
|
32
|
-
attribute ledger_attribute: 'EntityRef
|
33
|
-
resource_attribute:
|
32
|
+
attribute ledger_attribute: 'EntityRef',
|
33
|
+
resource_attribute: :entity,
|
34
|
+
type: LedgerSerializerType::EntityReferenceType
|
34
35
|
|
35
36
|
attribute ledger_attribute: 'DocNumber',
|
36
37
|
resource_attribute: :reference_number
|
@@ -16,7 +16,7 @@ module LedgerSync
|
|
16
16
|
required(:payment_type).filled(:string)
|
17
17
|
optional(:reference_number).maybe(:string)
|
18
18
|
optional(:transaction_date).filled(:date?)
|
19
|
-
optional(:
|
19
|
+
optional(:entity).hash(Types::Reference)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module LedgerSync
|
|
16
16
|
optional(:payment_type).maybe(:string)
|
17
17
|
optional(:reference_number).maybe(:string)
|
18
18
|
optional(:transaction_date).filled(:date?)
|
19
|
-
optional(:
|
19
|
+
optional(:entity).hash(Types::Reference)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -16,7 +16,7 @@ module LedgerSync
|
|
16
16
|
required(:payment_type).filled(:string)
|
17
17
|
optional(:reference_number).maybe(:string)
|
18
18
|
optional(:transaction_date).filled(:date?)
|
19
|
-
optional(:
|
19
|
+
optional(:entity).hash(Types::Reference)
|
20
20
|
end
|
21
21
|
end
|
22
22
|
end
|
@@ -12,9 +12,7 @@ module LedgerSync
|
|
12
12
|
deserialized_resource = super(hash: hash)
|
13
13
|
|
14
14
|
# Ref: https://github.com/LedgerSync/ledger_sync/issues/86
|
15
|
-
if deserialized_resource.is_a?(LedgerSync::Account) && deserialized_resource.account_type
|
16
|
-
deserialized_resource.classification ||= LedgerSerializerType::AccountType::TYPE_TO_CLASSIFICATION_MAPPING.fetch(deserialized_resource.account_type, nil)
|
17
|
-
end
|
15
|
+
deserialized_resource.classification ||= LedgerSerializerType::AccountType::TYPE_TO_CLASSIFICATION_MAPPING.fetch(deserialized_resource.account_type, nil) if deserialized_resource.is_a?(LedgerSync::Account) && deserialized_resource.account_type
|
18
16
|
|
19
17
|
return deserialized_resource unless merge_for_full_update
|
20
18
|
|
@@ -59,10 +57,6 @@ module LedgerSync
|
|
59
57
|
merged_resource
|
60
58
|
end
|
61
59
|
|
62
|
-
def self.id(**keywords)
|
63
|
-
super({ ledger_attribute: 'Id', resource_attribute: :ledger_id }.merge(keywords))
|
64
|
-
end
|
65
|
-
|
66
60
|
def to_ledger_hash(deep_merge_unmapped_values: {}, only_changes: false)
|
67
61
|
ret = super(only_changes: only_changes)
|
68
62
|
return ret unless deep_merge_unmapped_values.any?
|
@@ -73,8 +67,36 @@ module LedgerSync
|
|
73
67
|
)
|
74
68
|
end
|
75
69
|
|
70
|
+
class << self
|
71
|
+
attr_reader :quickbooks_online_resource_types_hash
|
72
|
+
end
|
73
|
+
|
74
|
+
def self.id(**keywords)
|
75
|
+
super({ ledger_attribute: 'Id', resource_attribute: :ledger_id }.merge(keywords))
|
76
|
+
end
|
77
|
+
|
78
|
+
def self.ledger_serializer_for(resource_class:)
|
79
|
+
QuickBooksOnline.const_get("#{resource_class.name.split('LedgerSync::')[1..-1].join('LedgerSync::')}::LedgerSerializer")
|
80
|
+
end
|
81
|
+
|
76
82
|
def self.quickbooks_online_resource_type(type = nil)
|
77
|
-
@quickbooks_online_resource_type ||=
|
83
|
+
@quickbooks_online_resource_type ||= begin
|
84
|
+
inferred_resource_class = _inferred_resource_class
|
85
|
+
qbo_type = (type || inferred_resource_class.resource_type).to_s
|
86
|
+
type_hash = QuickBooksOnline::LedgerSerializer.quickbooks_online_resource_types_hash.try(:fetch, qbo_type, nil)
|
87
|
+
raise "Cannot define type in #{name}. Type already exists: #{qbo_type}. Defined previously by #{quickbooks_online_resource_types_hash[qbo_type][:serializer_class].name}" if type_hash.present? && (type_hash[:serializer_class] != serializer_class || type_hash[:resource_class] != inferred_resource_class) if type_hash.present?
|
88
|
+
|
89
|
+
QuickBooksOnline::LedgerSerializer.class_eval do
|
90
|
+
@quickbooks_online_resource_types_hash ||= {}
|
91
|
+
end
|
92
|
+
|
93
|
+
QuickBooksOnline::LedgerSerializer.quickbooks_online_resource_types_hash[qbo_type] = {
|
94
|
+
resource_class: inferred_resource_class,
|
95
|
+
serializer_class: self
|
96
|
+
}
|
97
|
+
|
98
|
+
qbo_type
|
99
|
+
end
|
78
100
|
end
|
79
101
|
|
80
102
|
private
|
@@ -101,3 +123,6 @@ module LedgerSync
|
|
101
123
|
end
|
102
124
|
end
|
103
125
|
end
|
126
|
+
|
127
|
+
# Load other serializers to populate `QuickBooksOnline::LedgerSerializer.quickbooks_online_resource_types_hash`
|
128
|
+
Gem.find_files('ledger_sync/adaptors/quickbooks_online/**/ledger_serializer.rb').each { |path| require path }
|
@@ -4,7 +4,7 @@ module LedgerSync
|
|
4
4
|
module Adaptors
|
5
5
|
module QuickBooksOnline
|
6
6
|
module LedgerSerializerType
|
7
|
-
class AmountType < Adaptors::LedgerSerializerType::
|
7
|
+
class AmountType < Adaptors::LedgerSerializerType::ValueType
|
8
8
|
def convert_from_ledger(value:)
|
9
9
|
return if value.nil?
|
10
10
|
|
data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/entity_reference_type.rb
ADDED
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LedgerSync
|
4
|
+
module Adaptors
|
5
|
+
module QuickBooksOnline
|
6
|
+
module LedgerSerializerType
|
7
|
+
class EntityReferenceType < Adaptors::LedgerSerializerType::ValueType
|
8
|
+
def convert_from_ledger(value:)
|
9
|
+
return if value.nil?
|
10
|
+
|
11
|
+
raise "Unknown value type. Hash expected. Given: #{value.class.name}" unless value.is_a?(Hash)
|
12
|
+
return if value.empty?
|
13
|
+
|
14
|
+
value = LedgerSync::Util::HashHelpers.deep_stringify_keys(value)
|
15
|
+
resource_class = begin
|
16
|
+
quickbooks_online_type_hash = QuickBooksOnline::LedgerSerializer.quickbooks_online_resource_types_hash.fetch(value['type'].downcase, nil)
|
17
|
+
if quickbooks_online_type_hash.present?
|
18
|
+
quickbooks_online_type_hash.try(:fetch, :resource_class, nil)
|
19
|
+
else
|
20
|
+
LedgerSync.resources[value['type'].downcase.to_sym]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
raise "Unknown QuickBooks Online resource type: #{value['type']}" if resource_class.blank?
|
25
|
+
|
26
|
+
ret = resource_class.new(
|
27
|
+
ledger_id: value['value']
|
28
|
+
)
|
29
|
+
|
30
|
+
ret.display_name = value['name'] if ret.respond_to?(:display_name)
|
31
|
+
ret
|
32
|
+
end
|
33
|
+
|
34
|
+
def convert_from_local(value:)
|
35
|
+
return if value.nil?
|
36
|
+
raise "Resource expected. Given: #{value.class.name}" unless value.is_a?(LedgerSync::Resource)
|
37
|
+
|
38
|
+
ret = {
|
39
|
+
'value' => value.ledger_id
|
40
|
+
}
|
41
|
+
ret['name'] = value.display_name if value.respond_to?(:display_name)
|
42
|
+
ret['type'] = string_helpers.camelcase(
|
43
|
+
QuickBooksOnline::LedgerSerializer.ledger_serializer_for(
|
44
|
+
resource_class: value.class
|
45
|
+
).quickbooks_online_resource_type
|
46
|
+
)
|
47
|
+
ret
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def string_helpers
|
53
|
+
@string_helpers ||= LedgerSync::Util::StringHelpers
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -11,7 +11,7 @@ module LedgerSync
|
|
11
11
|
required(:external_id).maybe(:string)
|
12
12
|
required(:ledger_id).value(:nil)
|
13
13
|
required(:account).hash(Types::Reference)
|
14
|
-
required(:
|
14
|
+
required(:entity).hash(Types::Reference)
|
15
15
|
required(:currency).filled(:string)
|
16
16
|
required(:memo).filled(:string)
|
17
17
|
required(:payment_type).filled(:string)
|
@@ -21,36 +21,6 @@ module LedgerSync
|
|
21
21
|
required(:reference_number).filled(:string)
|
22
22
|
end
|
23
23
|
end
|
24
|
-
|
25
|
-
private
|
26
|
-
|
27
|
-
def operate
|
28
|
-
response = adaptor.post(
|
29
|
-
resource: 'purchase',
|
30
|
-
payload: local_resource_data
|
31
|
-
)
|
32
|
-
|
33
|
-
resource.ledger_id = response.dig('id')
|
34
|
-
success(
|
35
|
-
resource: Test::LedgerSerializer.new(resource: resource).deserialize(hash: response),
|
36
|
-
response: response
|
37
|
-
)
|
38
|
-
end
|
39
|
-
|
40
|
-
def local_resource_data
|
41
|
-
{
|
42
|
-
'currency' => resource.currency,
|
43
|
-
'account_id' => resource.account.ledger_id,
|
44
|
-
'vendor_id' => resource.vendor.ledger_id,
|
45
|
-
'line_items' => resource.line_items.map do |line_item|
|
46
|
-
{
|
47
|
-
'account_id' => line_item.account&.ledger_id,
|
48
|
-
'Amount' => line_item.amount / 100.0,
|
49
|
-
'description' => line_item.description
|
50
|
-
}
|
51
|
-
end
|
52
|
-
}
|
53
|
-
end
|
54
24
|
end
|
55
25
|
end
|
56
26
|
end
|
@@ -11,7 +11,7 @@ module LedgerSync
|
|
11
11
|
required(:external_id).maybe(:string)
|
12
12
|
required(:ledger_id).filled(:string)
|
13
13
|
required(:account).hash(Types::Reference)
|
14
|
-
required(:
|
14
|
+
required(:entity).hash(Types::Reference)
|
15
15
|
required(:currency).maybe(:string)
|
16
16
|
required(:memo).maybe(:string)
|
17
17
|
required(:payment_type).maybe(:string)
|
@@ -9,7 +9,7 @@ module LedgerSync
|
|
9
9
|
required(:external_id).maybe(:string)
|
10
10
|
required(:ledger_id).filled(:string)
|
11
11
|
required(:account).hash(Types::Reference)
|
12
|
-
required(:
|
12
|
+
required(:entity).hash(Types::Reference)
|
13
13
|
required(:currency).filled(:string)
|
14
14
|
required(:memo).filled(:string)
|
15
15
|
required(:payment_type).filled(:string)
|
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module LedgerSync
|
2
4
|
class Expense < LedgerSync::Resource
|
3
5
|
attribute :currency, type: Type::String
|
@@ -7,7 +9,7 @@ module LedgerSync
|
|
7
9
|
attribute :exchange_rate, type: Type::Float
|
8
10
|
attribute :reference_number, type: Type::String
|
9
11
|
|
10
|
-
references_one :
|
12
|
+
references_one :entity, to: [Customer, Vendor]
|
11
13
|
references_one :account, to: Account
|
12
14
|
|
13
15
|
references_many :line_items, to: ExpenseLineItem
|
@@ -13,7 +13,11 @@ module LedgerSync
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def error_message(attribute:, resource:, value:)
|
16
|
-
|
16
|
+
if resource_class.is_a?(Array)
|
17
|
+
"Attribute #{attribute.name} for #{resource.class.name} should be one of the following: #{resource_class.map(&:name).join(', ')}. Given #{value.class.name}"
|
18
|
+
else
|
19
|
+
"Attribute #{attribute.name} for #{resource.class.name} should be a #{resource_class.first.name}. Given #{value.class.name}"
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
def type
|
@@ -22,10 +26,20 @@ module LedgerSync
|
|
22
26
|
|
23
27
|
def valid_without_casting?(value:)
|
24
28
|
return true if value.nil?
|
25
|
-
return true if value.is_a?(
|
29
|
+
return true if resource_classes.select { |e| value.is_a?(e) }.any?
|
26
30
|
|
27
31
|
false
|
28
32
|
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def resource_classes
|
37
|
+
@resource_classes ||= if resource_class.is_a?(Array)
|
38
|
+
resource_class
|
39
|
+
else
|
40
|
+
[resource_class]
|
41
|
+
end
|
42
|
+
end
|
29
43
|
end
|
30
44
|
end
|
31
45
|
end
|
@@ -53,9 +53,10 @@ module LedgerSync
|
|
53
53
|
raise "Unrecognized attribute for #{resource_class.name}: #{k}" if attribute.nil? && !ignore_unrecognized_attributes
|
54
54
|
|
55
55
|
v = if attribute.is_a?(ResourceAttribute::Reference::One)
|
56
|
+
resource_type = resource_type_by(external_id: current_data[k])
|
56
57
|
resource_or_build(
|
57
58
|
external_id: current_data[k],
|
58
|
-
type:
|
59
|
+
type: resource_type
|
59
60
|
)
|
60
61
|
elsif attribute.is_a?(ResourceAttribute::Reference::Many)
|
61
62
|
current_data[k].map do |many_reference|
|
@@ -81,6 +82,19 @@ module LedgerSync
|
|
81
82
|
)
|
82
83
|
end
|
83
84
|
|
85
|
+
# This will break if multiple objects of different types have the same external_id
|
86
|
+
def external_id_to_type_hash
|
87
|
+
@external_id_to_type_hash ||= begin
|
88
|
+
ret = {}
|
89
|
+
data.each do |type, type_resources|
|
90
|
+
type_resources.keys.each do |external_id|
|
91
|
+
ret[external_id] = type
|
92
|
+
end
|
93
|
+
end
|
94
|
+
ret
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
84
98
|
def resource_key(external_id:, type:)
|
85
99
|
"#{type}/#{external_id}"
|
86
100
|
end
|
@@ -91,6 +105,10 @@ module LedgerSync
|
|
91
105
|
build_resource(**external_id_and_type)
|
92
106
|
)
|
93
107
|
end
|
108
|
+
|
109
|
+
def resource_type_by(external_id:)
|
110
|
+
external_id_to_type_hash[external_id.to_sym]
|
111
|
+
end
|
94
112
|
end
|
95
113
|
end
|
96
114
|
end
|
data/lib/ledger_sync/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ledger_sync
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.1.
|
4
|
+
version: 1.1.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Jackson
|
@@ -398,6 +398,7 @@ files:
|
|
398
398
|
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/amount_type.rb
|
399
399
|
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/classification_type.rb
|
400
400
|
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/date_type.rb
|
401
|
+
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/entity_reference_type.rb
|
401
402
|
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/journal_entry_line_item_type.rb
|
402
403
|
- lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/payment_type.rb
|
403
404
|
- lib/ledger_sync/adaptors/quickbooks_online/operation.rb
|
@@ -524,7 +525,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
524
525
|
- !ruby/object:Gem::Version
|
525
526
|
version: '0'
|
526
527
|
requirements: []
|
527
|
-
|
528
|
+
rubyforge_project:
|
529
|
+
rubygems_version: 2.7.6
|
528
530
|
signing_key:
|
529
531
|
specification_version: 4
|
530
532
|
summary: Sync common objects to accounting software.
|