ledger_sync 1.1.1 → 1.1.2
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/.gitignore +1 -0
- data/Gemfile.lock +1 -1
- data/README.md +2 -3
- data/lib/ledger_sync.rb +12 -6
- data/lib/ledger_sync/adaptors/ledger_serializer.rb +124 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_attribute.rb +148 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_attribute_set.rb +51 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/mapping_type.rb +41 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/references_many_type.rb +24 -0
- data/lib/ledger_sync/adaptors/ledger_serializer_type/value_type.rb +17 -0
- data/lib/ledger_sync/adaptors/operation.rb +15 -9
- data/lib/ledger_sync/adaptors/quickbooks_online/account/ledger_serializer.rb +21 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/create.rb +8 -36
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/account/operations/update.rb +4 -35
- data/lib/ledger_sync/adaptors/quickbooks_online/account/searcher.rb +3 -44
- data/lib/ledger_sync/adaptors/quickbooks_online/adaptor.rb +75 -28
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/ledger_serializer.rb +40 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/create.rb +9 -48
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/find.rb +10 -21
- data/lib/ledger_sync/adaptors/quickbooks_online/bill/operations/update.rb +9 -52
- data/lib/ledger_sync/adaptors/quickbooks_online/bill_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/ledger_serializer.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/create.rb +2 -25
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/find.rb +2 -14
- data/lib/ledger_sync/adaptors/quickbooks_online/customer/operations/update.rb +3 -30
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/ledger_serializer.rb +35 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/create.rb +2 -39
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/find.rb +2 -14
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit/operations/update.rb +4 -43
- data/lib/ledger_sync/adaptors/quickbooks_online/deposit_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/ledger_serializer.rb +48 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/create.rb +10 -51
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/find.rb +10 -22
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/operations/update.rb +10 -55
- data/lib/ledger_sync/adaptors/quickbooks_online/expense_line_item/ledger_serializer.rb +27 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/ledger_serializer.rb +32 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/create.rb +4 -37
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/find.rb +4 -15
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/operations/update.rb +5 -42
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry_line_item/ledger_serializer.rb +31 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer.rb +103 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/{account/mapping.rb → ledger_serializer_type/account_sub_type.rb} +128 -148
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/account_type.rb +51 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/amount_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/classification_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/date_type.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/journal_entry_line_item_type.rb +20 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/ledger_serializer_type/payment_type.rb +21 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation.rb +2 -7
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/create.rb +29 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/find.rb +31 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/full_update.rb +43 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/operation/sparse_update.rb +29 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/ledger_serializer.rb +23 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/create.rb +1 -24
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/payment/operations/update.rb +2 -29
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/ledger_serializer.rb +33 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/create.rb +1 -29
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/transfer/operations/update.rb +4 -35
- data/lib/ledger_sync/adaptors/quickbooks_online/util/adaptor_error_parser.rb +2 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/util/operation_error_parser.rb +2 -1
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/ledger_serializer.rb +25 -0
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/create.rb +1 -23
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/quickbooks_online/vendor/operations/update.rb +2 -29
- data/lib/ledger_sync/adaptors/test/account/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/account/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/account/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/account/operations/update.rb +8 -2
- data/lib/ledger_sync/adaptors/test/account/operations/valid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/customer/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/customer/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/customer/operations/update.rb +1 -24
- data/lib/ledger_sync/adaptors/test/customer/operations/valid.rb +3 -6
- data/lib/ledger_sync/adaptors/test/expense/operations/create.rb +8 -3
- data/lib/ledger_sync/adaptors/test/expense/operations/find.rb +4 -14
- data/lib/ledger_sync/adaptors/test/expense/operations/update.rb +2 -32
- data/lib/ledger_sync/adaptors/test/ledger_serializer.rb +64 -0
- data/lib/ledger_sync/adaptors/test/operation/create.rb +27 -0
- data/lib/ledger_sync/adaptors/test/operation/find.rb +29 -0
- data/lib/ledger_sync/adaptors/test/operation/update.rb +34 -0
- data/lib/ledger_sync/adaptors/test/payment/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/payment/operations/find.rb +5 -1
- data/lib/ledger_sync/adaptors/test/payment/operations/update.rb +1 -23
- data/lib/ledger_sync/adaptors/test/transfer/operations/create.rb +1 -22
- data/lib/ledger_sync/adaptors/test/transfer/operations/find.rb +1 -13
- data/lib/ledger_sync/adaptors/test/transfer/operations/update.rb +1 -25
- data/lib/ledger_sync/adaptors/test/vendor/operations/create.rb +5 -1
- data/lib/ledger_sync/adaptors/test/vendor/operations/find.rb +7 -1
- data/lib/ledger_sync/adaptors/test/vendor/operations/invalid.rb +1 -0
- data/lib/ledger_sync/adaptors/test/vendor/operations/update.rb +1 -23
- data/lib/ledger_sync/adaptors/test/vendor/operations/valid.rb +1 -0
- data/lib/ledger_sync/error/adaptor_errors.rb +17 -5
- data/lib/ledger_sync/error/operation_errors.rb +12 -5
- data/lib/ledger_sync/error/resource_errors.rb +5 -1
- data/lib/ledger_sync/resource.rb +33 -6
- data/lib/ledger_sync/resource_attribute.rb +4 -0
- data/lib/ledger_sync/resource_attribute/dirty_mixin.rb +16 -0
- data/lib/ledger_sync/resource_attribute/mixin.rb +19 -7
- data/lib/ledger_sync/resource_attribute/reference/many.rb +55 -1
- data/lib/ledger_sync/resource_attribute_set.rb +6 -7
- data/lib/ledger_sync/resources/account.rb +1 -1
- data/lib/ledger_sync/resources/bill.rb +1 -0
- data/lib/ledger_sync/resources/bill_line_item.rb +2 -0
- data/lib/ledger_sync/resources/expense.rb +5 -1
- data/lib/ledger_sync/resources/expense_line_item.rb +2 -0
- data/lib/ledger_sync/resources/journal_entry.rb +1 -0
- data/lib/ledger_sync/result.rb +4 -3
- data/lib/ledger_sync/type/id.rb +34 -0
- data/lib/ledger_sync/type/reference_many.rb +8 -2
- data/lib/ledger_sync/type/reference_one.rb +5 -0
- data/lib/ledger_sync/type/value_mixin.rb +12 -0
- data/lib/ledger_sync/util/hash_helpers.rb +16 -0
- data/lib/ledger_sync/version.rb +1 -1
- data/qa.rb +142 -0
- metadata +38 -5
- data/lib/ledger_sync/adaptors/quickbooks_online/expense/mapping.rb +0 -15
- data/lib/ledger_sync/adaptors/quickbooks_online/journal_entry/mapping.rb +0 -14
- data/lib/ledger_sync/error/sync_errors.rb +0 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53419559e8cc29609542a442a100a9ecf8fe4dff040f4233631f4e13c688c893
|
4
|
+
data.tar.gz: 707b1bc26a777fb442cce8052a8facff59ce715ddaf5a09c8c626b5e7867d0c7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: edf14189d54667014a36ab9959ae0ba60a980c80131ea1cf36507358da50151a7e0428cc785d72aba91d6dd7a4b81836f40d743fedf93efbb0c90b3b2f3eecc8
|
7
|
+
data.tar.gz: a8eb0c9a2d75b5a2177f480f3fe2dbe4410201fa59cab4d5abca51586612012271081242e5190f894caa9b218f5ee3e899c1fb42e171512bae949fd40c01a978
|
data/.gitignore
CHANGED
data/Gemfile.lock
CHANGED
data/README.md
CHANGED
@@ -189,7 +189,7 @@ puts LedgerSync::Payment.new(
|
|
189
189
|
},
|
190
190
|
external_id: "",
|
191
191
|
ledger_id: nil,
|
192
|
-
|
192
|
+
|
193
193
|
}
|
194
194
|
},
|
195
195
|
"LedgerSync::Customer/b3eab7ec00431a4ae0468fee72e5ba8f": {
|
@@ -201,8 +201,7 @@ puts LedgerSync::Payment.new(
|
|
201
201
|
email: nil,
|
202
202
|
phone_number: nil,
|
203
203
|
external_id: "",
|
204
|
-
ledger_id: nil
|
205
|
-
sync_token: nil
|
204
|
+
ledger_id: nil
|
206
205
|
}
|
207
206
|
}
|
208
207
|
}
|
data/lib/ledger_sync.rb
CHANGED
@@ -85,9 +85,20 @@ module LedgerSync
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def self.register_adaptor(adaptor_key)
|
88
|
+
adaptor_root_path = "ledger_sync/adaptors/#{adaptor_key}"
|
89
|
+
require "#{adaptor_root_path}/adaptor"
|
88
90
|
self.adaptors ||= LedgerSync::AdaptorConfigurationStore.new
|
89
91
|
self.adaptors.register_adaptor(adaptor_key)
|
92
|
+
|
90
93
|
yield(adaptors.send(adaptor_key))
|
94
|
+
|
95
|
+
adaptor_files = Gem.find_files("#{adaptor_root_path}/**/*.rb")
|
96
|
+
# Sort the files to include BFS-style as most dependencies are in parent folders
|
97
|
+
adaptor_files.sort { |a, b| a.count('/') <=> b.count('/') }.each do |path|
|
98
|
+
next if path.include?('config.rb')
|
99
|
+
|
100
|
+
require path
|
101
|
+
end
|
91
102
|
end
|
92
103
|
|
93
104
|
def self.register_resource(resource:)
|
@@ -105,12 +116,7 @@ end
|
|
105
116
|
# Adaptors
|
106
117
|
require 'ledger_sync/adaptors/adaptor'
|
107
118
|
require 'ledger_sync/adaptors/searcher'
|
108
|
-
|
109
|
-
next if path.include?('config.rb')
|
110
|
-
|
111
|
-
require path
|
112
|
-
end
|
113
|
-
|
119
|
+
require 'ledger_sync/adaptors/ledger_serializer'
|
114
120
|
Gem.find_files('ledger_sync/adaptors/**/config.rb').each { |path| require path }
|
115
121
|
|
116
122
|
# Register Resources
|
@@ -0,0 +1,124 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ledger_serializer_type/value_type'
|
4
|
+
require_relative 'ledger_serializer_attribute'
|
5
|
+
require_relative 'ledger_serializer_attribute_set'
|
6
|
+
Gem.find_files('ledger_sync/adaptors/ledger_serializer_type/**/*.rb').each { |path| require path }
|
7
|
+
|
8
|
+
module LedgerSync
|
9
|
+
module Adaptors
|
10
|
+
class LedgerSerializer
|
11
|
+
attr_reader :resource
|
12
|
+
|
13
|
+
def initialize(resource:)
|
14
|
+
@resource = resource
|
15
|
+
ensure_inferred_resource_class!
|
16
|
+
end
|
17
|
+
|
18
|
+
def attribute_value_from_ledger(hash:, ledger_serializer_attribute:, resource:)
|
19
|
+
ledger_serializer_attribute.value_from_ledger(
|
20
|
+
hash: hash,
|
21
|
+
resource: resource
|
22
|
+
)
|
23
|
+
end
|
24
|
+
|
25
|
+
def deserialize(hash:)
|
26
|
+
deserialize_into = resource.dup # Do not overwrite values in the resource
|
27
|
+
hash = Util::HashHelpers.deep_stringify_keys(hash)
|
28
|
+
|
29
|
+
self.class.attributes.each do |ledger_serializer_attribute|
|
30
|
+
next unless ledger_serializer_attribute.resource_attribute?
|
31
|
+
|
32
|
+
value = attribute_value_from_ledger(
|
33
|
+
hash: hash,
|
34
|
+
ledger_serializer_attribute: ledger_serializer_attribute,
|
35
|
+
resource: deserialize_into
|
36
|
+
)
|
37
|
+
|
38
|
+
deserialize_into.assign_attribute(
|
39
|
+
ledger_serializer_attribute.resource_attribute_dot_parts.first,
|
40
|
+
value
|
41
|
+
)
|
42
|
+
end
|
43
|
+
|
44
|
+
deserialize_into
|
45
|
+
end
|
46
|
+
|
47
|
+
def to_ledger_hash(only_changes: false)
|
48
|
+
ret = {}
|
49
|
+
|
50
|
+
self.class.attributes.each do |ledger_serializer_attribute|
|
51
|
+
next if only_changes && !resource.attribute_changed?(ledger_serializer_attribute.resource_attribute)
|
52
|
+
|
53
|
+
ret = Util::HashHelpers.deep_merge(
|
54
|
+
hash_to_merge_into: ret,
|
55
|
+
other_hash: ledger_serializer_attribute.ledger_attribute_hash_for(resource: resource)
|
56
|
+
)
|
57
|
+
end
|
58
|
+
|
59
|
+
ret
|
60
|
+
end
|
61
|
+
|
62
|
+
def self.attribute(ledger_attribute:, resource_attribute: nil, type: LedgerSerializerType::ValueType, &block)
|
63
|
+
_attribute(
|
64
|
+
block: (block if block_given?),
|
65
|
+
ledger_attribute: ledger_attribute,
|
66
|
+
resource_attribute: resource_attribute,
|
67
|
+
type: type
|
68
|
+
)
|
69
|
+
end
|
70
|
+
|
71
|
+
def self.attributes
|
72
|
+
@attributes ||= LedgerSerializerAttributeSet.new(serializer_class: self)
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.references_many(ledger_attribute:, resource_attribute:, serializer:)
|
76
|
+
_attribute(
|
77
|
+
ledger_attribute: ledger_attribute,
|
78
|
+
resource_attribute: resource_attribute,
|
79
|
+
serializer: serializer,
|
80
|
+
type: LedgerSerializerType::ReferencesManyType
|
81
|
+
)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.id(ledger_attribute:, resource_attribute:, &block)
|
85
|
+
@id ||= _attribute(
|
86
|
+
block: (block if block_given?),
|
87
|
+
id: true,
|
88
|
+
ledger_attribute: ledger_attribute,
|
89
|
+
resource_attribute: resource_attribute
|
90
|
+
)
|
91
|
+
end
|
92
|
+
|
93
|
+
def self._inferred_resource_class
|
94
|
+
parts = name.split('::')
|
95
|
+
LedgerSync.const_get(parts[parts.index('Adaptors') + 2])
|
96
|
+
end
|
97
|
+
|
98
|
+
private_class_method def self._attribute(**keywords)
|
99
|
+
attributes.add(
|
100
|
+
_build_attribute(**keywords)
|
101
|
+
)
|
102
|
+
end
|
103
|
+
|
104
|
+
private_class_method def self._build_attribute(block: nil, id: false, ledger_attribute:, resource_attribute: nil, resource_class: nil, serializer: nil, type: LedgerSerializerType::ValueType)
|
105
|
+
LedgerSerializerAttribute.new(
|
106
|
+
id: id,
|
107
|
+
block: block,
|
108
|
+
ledger_attribute: ledger_attribute,
|
109
|
+
resource_attribute: resource_attribute,
|
110
|
+
resource_class: resource_class,
|
111
|
+
serializer: serializer,
|
112
|
+
type: type
|
113
|
+
)
|
114
|
+
end
|
115
|
+
|
116
|
+
private
|
117
|
+
|
118
|
+
def ensure_inferred_resource_class!
|
119
|
+
inferred_resource_class = self.class._inferred_resource_class
|
120
|
+
raise "Resource must be a #{inferred_resource_class.name}. Given #{resource.class}" unless resource.is_a?(inferred_resource_class)
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -0,0 +1,148 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'ledger_serializer_type/value_type'
|
4
|
+
Gem.find_files('ledger_sync/adaptors/ledger_serializer_type/**/*.rb').each { |path| require path }
|
5
|
+
|
6
|
+
module LedgerSync
|
7
|
+
module Adaptors
|
8
|
+
class LedgerSerializerAttribute
|
9
|
+
attr_reader :block,
|
10
|
+
:id,
|
11
|
+
:ledger_attribute,
|
12
|
+
:resource_attribute,
|
13
|
+
:resource_class,
|
14
|
+
:serializer,
|
15
|
+
:type
|
16
|
+
|
17
|
+
def initialize(block: nil, id: false, ledger_attribute:, resource_attribute: nil, resource_class: nil, serializer: nil, type: LedgerSerializerType::ValueType)
|
18
|
+
raise 'block and resource_attribute cannot both be present' unless block.nil? || resource_attribute.nil?
|
19
|
+
|
20
|
+
@block = block
|
21
|
+
@id = id
|
22
|
+
@ledger_attribute = ledger_attribute.to_s
|
23
|
+
@resource_attribute = resource_attribute.to_s
|
24
|
+
@resource_class = resource_class
|
25
|
+
@serializer = serializer
|
26
|
+
@type = type.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def block_value_for(resource:)
|
30
|
+
block.call(resource)
|
31
|
+
end
|
32
|
+
|
33
|
+
# Make nested/dot calls (e.g. `vendor.ledger_id`)
|
34
|
+
def dot_value_for(resource:)
|
35
|
+
resource_attribute_dot_parts.inject(resource) { |r, dot_method| r&.send(dot_method) }
|
36
|
+
end
|
37
|
+
|
38
|
+
def ledger_attribute_dot_parts
|
39
|
+
@ledger_attribute_dot_parts ||= ledger_attribute.split('.')
|
40
|
+
end
|
41
|
+
|
42
|
+
def ledger_attribute_hash_for(resource:)
|
43
|
+
ledger_attribute_hash_with(value: value_from_local(resource: resource))
|
44
|
+
end
|
45
|
+
|
46
|
+
# Create nested hash for ledger
|
47
|
+
#
|
48
|
+
# when ledger_attribute = 'Foo.Bar.Baz',
|
49
|
+
# ledger_attribute_hash_with(value: 123)
|
50
|
+
# Result:
|
51
|
+
# {
|
52
|
+
# 'Foo' => {
|
53
|
+
# 'Bar' => {
|
54
|
+
# 'Baz' => 123
|
55
|
+
# }
|
56
|
+
# }
|
57
|
+
# }
|
58
|
+
def ledger_attribute_hash_with(value:)
|
59
|
+
ledger_attribute_dot_parts.reverse.inject(value) { |a, n| { n => a } }
|
60
|
+
end
|
61
|
+
|
62
|
+
def references_many?
|
63
|
+
type.is_a?(LedgerSerializerType::ReferencesManyType)
|
64
|
+
end
|
65
|
+
|
66
|
+
def resource_attribute?
|
67
|
+
resource_attribute.present?
|
68
|
+
end
|
69
|
+
|
70
|
+
def resource_attribute_dot_parts
|
71
|
+
@resource_attribute_dot_parts ||= resource_attribute.split('.')
|
72
|
+
end
|
73
|
+
|
74
|
+
def value_from_local(resource:)
|
75
|
+
value = if block.nil?
|
76
|
+
dot_value_for(resource: resource)
|
77
|
+
else
|
78
|
+
block_value_for(resource: resource)
|
79
|
+
end
|
80
|
+
|
81
|
+
if references_many?
|
82
|
+
type.convert_from_local(
|
83
|
+
serializer: serializer,
|
84
|
+
value: value
|
85
|
+
)
|
86
|
+
else
|
87
|
+
type.convert_from_local(
|
88
|
+
value: value
|
89
|
+
)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def value_from_ledger(hash:, resource:)
|
94
|
+
value = hash.dig(*ledger_attribute_dot_parts)
|
95
|
+
|
96
|
+
value = if references_many?
|
97
|
+
type.convert_from_ledger(
|
98
|
+
resource_class: resource_class,
|
99
|
+
serializer: serializer,
|
100
|
+
value: value
|
101
|
+
)
|
102
|
+
else
|
103
|
+
type.convert_from_ledger(
|
104
|
+
value: value
|
105
|
+
)
|
106
|
+
end
|
107
|
+
|
108
|
+
return value if resource_attribute_dot_parts.count <= 1
|
109
|
+
|
110
|
+
nested_resource = resource.send(resource_attribute_dot_parts.first)
|
111
|
+
nested_resource ||= resource_attribute_class(resource: resource).new
|
112
|
+
|
113
|
+
build_resource_value_from_nested_attributes(
|
114
|
+
nested_resource,
|
115
|
+
value,
|
116
|
+
resource_attribute_dot_parts[1..-1]
|
117
|
+
)
|
118
|
+
end
|
119
|
+
|
120
|
+
private
|
121
|
+
|
122
|
+
def build_resource_value_from_nested_attributes(resource, value, attribute_parts)
|
123
|
+
resource = resource.dup
|
124
|
+
first_attribute, *remaining_attributes = attribute_parts
|
125
|
+
|
126
|
+
if remaining_attributes.count.zero?
|
127
|
+
resource.public_send("#{first_attribute}=", value)
|
128
|
+
else
|
129
|
+
resource.public_send(
|
130
|
+
"#{first_attribute}=",
|
131
|
+
build_resource_value_from_nested_attributes(
|
132
|
+
resource.public_send(first_attribute) || resource.class.resource_attributes[first_attribute.to_sym].type.resource_class.new,
|
133
|
+
value,
|
134
|
+
remaining_attributes
|
135
|
+
)
|
136
|
+
)
|
137
|
+
end
|
138
|
+
|
139
|
+
resource
|
140
|
+
end
|
141
|
+
|
142
|
+
def resource_attribute_class(resource:)
|
143
|
+
@resource_attribute_type ||= {}
|
144
|
+
@resource_attribute_type[resource] ||= resource.class.resource_attributes[resource_attribute_dot_parts.first.to_sym].type.resource_class
|
145
|
+
end
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LedgerSync
|
4
|
+
module Adaptors
|
5
|
+
class LedgerSerializerAttributeSet
|
6
|
+
attr_reader :attributes,
|
7
|
+
:id_attribute,
|
8
|
+
:ledger_attribute_keyed_hash,
|
9
|
+
:resource_attribute_keyed_hash,
|
10
|
+
:serializer_class
|
11
|
+
|
12
|
+
delegate :[],
|
13
|
+
:each,
|
14
|
+
:include?,
|
15
|
+
:map,
|
16
|
+
to: :attributes
|
17
|
+
|
18
|
+
def initialize(serializer_class:)
|
19
|
+
@attributes = []
|
20
|
+
@ledger_attribute_keyed_hash = {}
|
21
|
+
@resource_attribute_keyed_hash = {}
|
22
|
+
@serializer_class = serializer_class
|
23
|
+
end
|
24
|
+
|
25
|
+
def add(attribute)
|
26
|
+
@attributes << attribute
|
27
|
+
@id_attribute = attribute if attribute.id
|
28
|
+
if attribute.ledger_attribute.present?
|
29
|
+
raise "ledger_attribute already defined for #{serializer_class.name}: #{attribute.ledger_attribute}" if ledger_attribute_keyed_hash.key?(attribute.ledger_attribute.to_s)
|
30
|
+
|
31
|
+
ledger_attribute_keyed_hash[attribute.ledger_attribute.to_s] = attribute
|
32
|
+
end
|
33
|
+
|
34
|
+
if attribute.resource_attribute.present?
|
35
|
+
raise "resource_attribute already defined for #{serializer_class.name}: #{attribute.resource_attribute}" if resource_attribute_keyed_hash.key?(attribute.resource_attribute.to_s)
|
36
|
+
|
37
|
+
resource_attribute_keyed_hash[attribute.resource_attribute.to_s] = attribute
|
38
|
+
end
|
39
|
+
|
40
|
+
# TODO: Can make this validate something like `expense.vendor.id`
|
41
|
+
# raise "#{resource_attribute} is not an attribute of the resource #{_inferred_resource_class}" if !resource_attribute.nil? && !_inferred_resource_class.serialize_attribute?(resource_attribute)
|
42
|
+
|
43
|
+
attribute
|
44
|
+
end
|
45
|
+
|
46
|
+
def ledger_attribute?(key)
|
47
|
+
ledger_attribute_keyed_hash.include?(key.to_s)
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module LedgerSync
|
4
|
+
module Adaptors
|
5
|
+
module LedgerSerializerType
|
6
|
+
class MappingType < ValueType
|
7
|
+
attr_reader :source, :value
|
8
|
+
|
9
|
+
def self.mapping
|
10
|
+
@mapping ||= begin
|
11
|
+
raise NotImplementedError
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
def convert_from_ledger(value:)
|
16
|
+
return if value.nil?
|
17
|
+
raise "Ledger to local mapping not found: #{value}" unless reverse_mapping_hash.key?(value)
|
18
|
+
|
19
|
+
reverse_mapping_hash[value]
|
20
|
+
end
|
21
|
+
|
22
|
+
def convert_from_local(value:)
|
23
|
+
return if value.nil?
|
24
|
+
raise "Local to ledger mapping not found: #{value}" unless mapping_hash.key?(value)
|
25
|
+
|
26
|
+
mapping_hash[value]
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def mapping_hash
|
32
|
+
@mapping_hash ||= self.class.mapping
|
33
|
+
end
|
34
|
+
|
35
|
+
def reverse_mapping_hash
|
36
|
+
@reverse_mapping_hash ||= mapping_hash.to_a.map(&:reverse).to_h
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|