maestrano-connector-rails 1.2.3 → 1.3.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (29) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop_todo.yml +7 -20
  3. data/VERSION +1 -1
  4. data/app/controllers/maestrano/synchronizations_controller.rb +3 -3
  5. data/app/models/maestrano/connector/rails/concerns/complex_entity.rb +50 -22
  6. data/app/models/maestrano/connector/rails/concerns/connec_helper.rb +157 -19
  7. data/app/models/maestrano/connector/rails/concerns/entity.rb +63 -42
  8. data/app/models/maestrano/connector/rails/concerns/external.rb +4 -0
  9. data/app/models/maestrano/connector/rails/concerns/sub_entity_base.rb +18 -5
  10. data/app/models/maestrano/connector/rails/organization.rb +1 -1
  11. data/lib/generators/connector/templates/complex_entity_example/contact_and_lead.rb +5 -5
  12. data/lib/generators/connector/templates/entity.rb +4 -5
  13. data/lib/generators/connector/templates/external.rb +6 -0
  14. data/lib/generators/connector/templates/home_index.haml +7 -4
  15. data/maestrano-connector-rails.gemspec +7 -4
  16. data/release_notes.md +5 -0
  17. data/spec/factories.rb +2 -2
  18. data/spec/integration/complex_id_references_spec.rb +248 -0
  19. data/spec/integration/complex_naming_spec.rb +191 -0
  20. data/spec/integration/{integration_complex_spec.rb → complex_spec.rb} +9 -9
  21. data/spec/integration/connec_to_external_spec.rb +7 -3
  22. data/spec/integration/id_references_spec.rb +581 -0
  23. data/spec/integration/singleton_spec.rb +3 -3
  24. data/spec/models/complex_entity_spec.rb +42 -27
  25. data/spec/models/connec_helper_spec.rb +399 -31
  26. data/spec/models/entity_spec.rb +76 -21
  27. data/spec/models/external_spec.rb +4 -0
  28. data/spec/models/sub_entity_base_spec.rb +11 -4
  29. metadata +6 -3
@@ -0,0 +1,248 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'complex id references' do
4
+
5
+ class Entities::IdPayment < Maestrano::Connector::Rails::ComplexEntity
6
+ def self.connec_entities_names
7
+ %w(IdPayment)
8
+ end
9
+ def self.external_entities_names
10
+ %w(IdBill)
11
+ end
12
+ def connec_model_to_external_model(connec_hash_of_entities)
13
+ {'IdPayment' => {'IdBill' => connec_hash_of_entities['IdPayment']}}
14
+ end
15
+ def external_model_to_connec_model(external_hash_of_entities)
16
+ {'IdBill' => {'IdPayment' => external_hash_of_entities['IdBill']}}
17
+ end
18
+ end
19
+
20
+ module Entities::SubEntities
21
+ end
22
+ class Entities::SubEntities::IdPayment < Maestrano::Connector::Rails::SubEntityBase
23
+ def self.external?
24
+ false
25
+ end
26
+ def self.entity_name
27
+ 'IdPayment'
28
+ end
29
+ def self.mapper_classes
30
+ {
31
+ 'IdBill' => ::IdPaymentMapper
32
+ }
33
+ end
34
+ def self.object_name_from_connec_entity_hash(entity)
35
+ entity['title']
36
+ end
37
+ def self.references
38
+ {'IdBill' => {record_references: %w(organization_id), id_references: %w(lines/id)}}
39
+ end
40
+ def self.id_from_external_entity_hash(entity)
41
+ entity['ID']
42
+ end
43
+ end
44
+
45
+ class Entities::SubEntities::IdBill < Maestrano::Connector::Rails::SubEntityBase
46
+ def self.external?
47
+ true
48
+ end
49
+ def self.entity_name
50
+ 'IdBill'
51
+ end
52
+ def self.mapper_classes
53
+ {'IdPayment' => ::IdPaymentMapper}
54
+ end
55
+ def self.id_from_external_entity_hash(entity)
56
+ entity['ID']
57
+ end
58
+ def self.references
59
+ {'IdPayment' => {record_references: %w(organization_id), id_references: %w(lines/id)}}
60
+ end
61
+ end
62
+
63
+ class IdLineMapper
64
+ extend HashMapper
65
+ map from('id'), to('ID')
66
+ map from('amount'), to('Price')
67
+ end
68
+
69
+ class IdPaymentMapper
70
+ extend HashMapper
71
+ map from('title'), to('Title')
72
+ map from('organization_id'), to('AccountId')
73
+ map from('lines'), to('Line'), using: IdLineMapper
74
+ end
75
+
76
+ let(:provider) { 'provider' }
77
+ let(:oauth_uid) { 'oauth uid' }
78
+ let!(:organization) { create(:organization, oauth_provider: provider, oauth_uid: oauth_uid) }
79
+ let(:connec_client) { Maestrano::Connector::Rails::ConnecHelper.get_client(organization) }
80
+ let(:external_client) { Object.new }
81
+ let(:connec_payment_id) { '1205c5e0-e18e-0133-890f-07d4de9f9781' }
82
+ let(:connec_line_id1) { '3405c5e0-e18e-0133-890f-07d4de9f9781' }
83
+ let(:connec_line_id2) { '4505c5e0-e18e-0133-890f-07d4de9f9781' }
84
+ let(:ext_payment_id) { 'ext payment id' }
85
+ let(:ext_org_id) { 'ext org id' }
86
+ let(:ext_line_id1) { 'ext line id1' }
87
+ let(:ext_line_id2) { 'ext line id2' }
88
+
89
+ let(:payment_title) { 'This is a payment' }
90
+
91
+ before {
92
+ allow(Maestrano::Connector::Rails::External).to receive(:entities_list).and_return(%w(id_payment))
93
+
94
+ allow(connec_client).to receive(:get).and_return(ActionDispatch::Response.new(200, {}, {idpayments: [connec_payment]}.to_json, {}))
95
+ allow(connec_client).to receive(:batch).and_return(ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {payments: {}}}]}.to_json, {}))
96
+
97
+ allow_any_instance_of(Entities::SubEntities::IdBill).to receive(:get_external_entities).and_return([])
98
+ }
99
+
100
+ subject { Maestrano::Connector::Rails::SynchronizationJob.new.sync_entity('id_payment', organization, connec_client, external_client, organization.last_synchronization_date, {}) }
101
+
102
+ describe 'a creation from connec' do
103
+ before {
104
+ allow_any_instance_of(Entities::SubEntities::IdPayment).to receive(:create_external_entity).and_return(entity_received_after_creation)
105
+ }
106
+
107
+ let(:connec_payment) {
108
+ {
109
+ 'id' => [
110
+ {
111
+ 'realm' => 'org-fg4a',
112
+ 'provider' => 'connec',
113
+ 'id' => connec_payment_id
114
+ }
115
+ ],
116
+ 'title' => payment_title,
117
+ 'organization_id' => [
118
+ {
119
+ 'realm' => 'org-fg4a',
120
+ 'provider' => 'connec',
121
+ 'id' => '2305c5e0-e18e-0133-890f-07d4de9f9781'
122
+ },
123
+ {
124
+ 'realm' => oauth_uid,
125
+ 'provider' => provider,
126
+ 'id' => ext_org_id
127
+ }
128
+ ],
129
+ 'lines' => lines
130
+ }
131
+ }
132
+
133
+ let(:lines) {
134
+ [
135
+ {
136
+ 'id' => [
137
+ {
138
+ 'realm' => 'org-fg4a',
139
+ 'provider' => 'connec',
140
+ 'id' => connec_line_id1
141
+ }
142
+ ],
143
+ 'amount' => 123
144
+ },
145
+ {
146
+ 'id' => [
147
+ {
148
+ 'realm' => 'org-fg4a',
149
+ 'provider' => 'connec',
150
+ 'id' => connec_line_id2
151
+ }
152
+ ],
153
+ 'amount' => 456
154
+ }
155
+ ]
156
+ }
157
+
158
+ let(:entity_received_after_creation) {
159
+ {
160
+ 'ID' => ext_payment_id,
161
+ 'Title' => payment_title,
162
+ 'AccountId' => ext_org_id,
163
+ 'Line' => [
164
+ {
165
+ 'ID' => ext_line_id1,
166
+ 'Price' => 123
167
+ },
168
+ {
169
+ 'ID' => ext_line_id2,
170
+ 'Price' => 456
171
+ }
172
+ ]
173
+ }
174
+ }
175
+
176
+ let(:batch_params) {
177
+ {
178
+ :sequential=>true,
179
+ :ops=> [
180
+ {
181
+ :method=>"put",
182
+ :url=>"/api/v2/#{organization.uid}/idpayments/#{connec_payment_id}",
183
+ :params=>
184
+ {
185
+ :idpayments=>{
186
+ 'id' => [
187
+ {
188
+ 'id' => ext_payment_id,
189
+ 'provider' =>provider,
190
+ 'realm' =>oauth_uid
191
+ }
192
+ ],
193
+ 'lines' => [
194
+ {
195
+ 'id' => [
196
+ {
197
+ 'realm' => 'org-fg4a',
198
+ 'provider' => 'connec',
199
+ 'id' => connec_line_id1
200
+ },
201
+ {
202
+ 'realm' => oauth_uid,
203
+ 'provider' => provider,
204
+ 'id' => ext_line_id1
205
+ }
206
+ ]
207
+ },
208
+ {
209
+ 'id' => [
210
+ {
211
+ 'realm' => 'org-fg4a',
212
+ 'provider' => 'connec',
213
+ 'id' => connec_line_id2
214
+ },
215
+ {
216
+ 'realm' => oauth_uid,
217
+ 'provider' => provider,
218
+ 'id' => ext_line_id2
219
+ }
220
+ ]
221
+ }
222
+ ]
223
+ }
224
+ }
225
+ }
226
+ ]
227
+ }
228
+ }
229
+
230
+ it 'handles the idmap correctly' do
231
+ expect{
232
+ subject
233
+ }.to change{ Maestrano::Connector::Rails::IdMap.count }.by(1)
234
+ idmap = Maestrano::Connector::Rails::IdMap.last
235
+ expect(idmap.name).to eql(payment_title)
236
+ expect(idmap.connec_entity).to eql('idpayment')
237
+ expect(idmap.external_entity).to eql('idbill')
238
+ expect(idmap.message).to be_nil
239
+ expect(idmap.external_id).to eql(ext_payment_id)
240
+ expect(idmap.connec_id).to eql(connec_payment_id)
241
+ end
242
+
243
+ it 'send the external id to connec' do
244
+ expect(connec_client).to receive(:batch).with(batch_params)
245
+ subject
246
+ end
247
+ end
248
+ end
@@ -0,0 +1,191 @@
1
+ require 'spec_helper'
2
+
3
+ describe 'complex entity subentities naming conflict' do
4
+
5
+ class Entities::NamePayment < Maestrano::Connector::Rails::ComplexEntity
6
+ def self.connec_entities_names
7
+ {Payment: 'NamePayment'}
8
+ end
9
+ def self.external_entities_names
10
+ {Payment: 'ExtPayment'}
11
+ end
12
+ def connec_model_to_external_model(connec_hash_of_entities)
13
+ {'Payment' => {'Payment' => connec_hash_of_entities['Payment']}}
14
+ end
15
+ def external_model_to_connec_model(external_hash_of_entities)
16
+ {'Payment' => {'Payment' => external_hash_of_entities['Payment']}}
17
+ end
18
+ end
19
+
20
+ module Entities::SubEntities
21
+ end
22
+ class Entities::SubEntities::NamePayment < Maestrano::Connector::Rails::SubEntityBase
23
+ def self.external?
24
+ false
25
+ end
26
+ def self.entity_name
27
+ 'Payment'
28
+ end
29
+ def self.mapper_classes
30
+ {
31
+ 'Payment' => ::PaymentMapper
32
+ }
33
+ end
34
+ def self.object_name_from_connec_entity_hash(entity)
35
+ entity['title']
36
+ end
37
+ def self.references
38
+ {'Payment' => {record_references: %w(organization_id), id_references: %w(lines/id)}}
39
+ end
40
+ def self.id_from_external_entity_hash(entity)
41
+ entity['ID']
42
+ end
43
+ end
44
+
45
+ class Entities::SubEntities::ExtPayment < Maestrano::Connector::Rails::SubEntityBase
46
+ def self.external?
47
+ true
48
+ end
49
+ def self.entity_name
50
+ 'Payment'
51
+ end
52
+ def self.mapper_classes
53
+ {'Payment' => ::PaymentMapper}
54
+ end
55
+ def self.id_from_external_entity_hash(entity)
56
+ entity['ID']
57
+ end
58
+ def self.references
59
+ {'Payment' => {record_references: %w(organization_id), id_references: %w(lines/id)}}
60
+ end
61
+ end
62
+
63
+ class LineMapper
64
+ extend HashMapper
65
+ map from('id'), to('ID')
66
+ map from('amount'), to('Price')
67
+ end
68
+
69
+ class PaymentMapper
70
+ extend HashMapper
71
+ map from('title'), to('Title')
72
+ map from('organization_id'), to('AccountId')
73
+ map from('lines'), to('Line'), using: LineMapper
74
+ end
75
+
76
+ let(:provider) { 'provider' }
77
+ let(:oauth_uid) { 'oauth uid' }
78
+ let!(:organization) { create(:organization, oauth_provider: provider, oauth_uid: oauth_uid) }
79
+ let(:connec_client) { Maestrano::Connector::Rails::ConnecHelper.get_client(organization) }
80
+ let(:external_client) { Object.new }
81
+ let(:connec_payment_id) { '1205c5e0-e18e-0133-890f-07d4de9f9781' }
82
+ let(:connec_line_id1) { '3405c5e0-e18e-0133-890f-07d4de9f9781' }
83
+ let(:ext_payment_id) { 'ext payment id' }
84
+ let(:ext_org_id) { 'ext org id' }
85
+ let(:ext_line_id1) { 'ext line id1' }
86
+ let(:payment_title) { 'This is a payment' }
87
+
88
+ before {
89
+ allow(Maestrano::Connector::Rails::External).to receive(:entities_list).and_return(%w(name_payment))
90
+ }
91
+
92
+ subject { Maestrano::Connector::Rails::SynchronizationJob.new.sync_entity('name_payment', organization, connec_client, external_client, organization.last_synchronization_date, {}) }
93
+
94
+ describe 'fetching entities from external' do
95
+ before {
96
+ allow_any_instance_of(Entities::SubEntities::NamePayment).to receive(:get_connec_entities).and_return([])
97
+ }
98
+
99
+ it 'does a fetch with the right name' do
100
+ expect_any_instance_of(Entities::SubEntities::ExtPayment).to receive(:get_external_entities).with('Payment', organization.last_synchronization_date).and_return([])
101
+ subject
102
+ end
103
+ end
104
+
105
+ describe 'sending entities to external' do
106
+ before {
107
+ allow(connec_client).to receive(:get).and_return(ActionDispatch::Response.new(200, {}, {payments: [connec_payment]}.to_json, {}))
108
+ allow(connec_client).to receive(:batch).and_return(ActionDispatch::Response.new(200, {}, {results: [{status: 200, body: {payments: {}}}]}.to_json, {}))
109
+
110
+ allow_any_instance_of(Entities::SubEntities::ExtPayment).to receive(:get_external_entities).and_return([])
111
+ }
112
+
113
+ let(:connec_payment) {
114
+ {
115
+ 'id' => [
116
+ {
117
+ 'realm' => 'org-fg4a',
118
+ 'provider' => 'connec',
119
+ 'id' => connec_payment_id
120
+ }
121
+ ],
122
+ 'title' => payment_title,
123
+ 'organization_id' => [
124
+ {
125
+ 'realm' => 'org-fg4a',
126
+ 'provider' => 'connec',
127
+ 'id' => '2305c5e0-e18e-0133-890f-07d4de9f9781'
128
+ },
129
+ {
130
+ 'realm' => oauth_uid,
131
+ 'provider' => provider,
132
+ 'id' => ext_org_id
133
+ }
134
+ ],
135
+ 'lines' => lines
136
+ }
137
+ }
138
+
139
+ let(:lines) {
140
+ [
141
+ {
142
+ 'id' => [
143
+ {
144
+ 'realm' => 'org-fg4a',
145
+ 'provider' => 'connec',
146
+ 'id' => connec_line_id1
147
+ }
148
+ ],
149
+ 'amount' => 123
150
+ }
151
+ ]
152
+ }
153
+
154
+ let(:mapped_payment) {
155
+ {
156
+ "Title"=>"This is a payment",
157
+ "AccountId"=>"ext org id",
158
+ "Line"=>[{"Price"=>123}]}
159
+ }
160
+
161
+ before {
162
+ allow_any_instance_of(Entities::SubEntities::NamePayment).to receive(:create_external_entity).and_return({'ID' => ext_payment_id})
163
+ }
164
+
165
+ it 'handles the idmap correctly' do
166
+ expect{
167
+ subject
168
+ }.to change{ Maestrano::Connector::Rails::IdMap.count }.by(1)
169
+ idmap = Maestrano::Connector::Rails::IdMap.last
170
+ expect(idmap.name).to eql(payment_title)
171
+ expect(idmap.connec_entity).to eql('payment')
172
+ expect(idmap.external_entity).to eql('payment')
173
+ expect(idmap.message).to be_nil
174
+ expect(idmap.external_id).to eql(ext_payment_id)
175
+ expect(idmap.connec_id).to eql(connec_payment_id)
176
+ end
177
+
178
+ it 'handles the mapping correctly' do
179
+ payment_idmap = Entities::SubEntities::NamePayment.create_idmap(organization_id: organization.id, external_id: ext_payment_id, connec_entity: 'payment')
180
+ allow(Maestrano::Connector::Rails::IdMap).to receive(:create).and_return(payment_idmap)
181
+ expect_any_instance_of(Entities::NamePayment).to receive(:push_entities_to_external).with({'Payment' => {'Payment' => [{entity: mapped_payment.with_indifferent_access, idmap: payment_idmap, id_refs_only_connec_entity: {'lines' => lines.map { |l| l.delete('amount'); l }}}]}})
182
+ subject
183
+ end
184
+
185
+ it 'handles the sending with the correct names' do
186
+ expect_any_instance_of(Entities::SubEntities::NamePayment).to receive(:create_external_entity).once.with(mapped_payment, 'Payment').and_return({})
187
+ expect(connec_client).to receive(:batch).once.and_return(ActionDispatch::Response.new(201, {}, {results: []}.to_json, {}))
188
+ subject
189
+ end
190
+ end
191
+ end
@@ -10,16 +10,16 @@ describe 'complex entities workflow' do
10
10
  end
11
11
  def connec_model_to_external_model(connec_hash_of_entities)
12
12
  organizations = connec_hash_of_entities['CompOrganization']
13
- modeled_connec_entities = {'CompOrganization' => { 'CompSupplier' => [], 'CompCustomer' => [] }}
13
+ modelled_connec_entities = {'CompOrganization' => { 'CompSupplier' => [], 'CompCustomer' => [] }}
14
14
 
15
15
  organizations.each do |organization|
16
16
  if organization['is_supplier']
17
- modeled_connec_entities['CompOrganization']['CompSupplier'] << organization
17
+ modelled_connec_entities['CompOrganization']['CompSupplier'] << organization
18
18
  else
19
- modeled_connec_entities['CompOrganization']['CompCustomer'] << organization
19
+ modelled_connec_entities['CompOrganization']['CompCustomer'] << organization
20
20
  end
21
21
  end
22
- return modeled_connec_entities
22
+ return modelled_connec_entities
23
23
  end
24
24
  def external_model_to_connec_model(external_hash_of_entities)
25
25
  return {'CompCustomer' => {'CompOrganization' => external_hash_of_entities['CompCustomer']}, 'CompSupplier' => {'CompOrganization' => external_hash_of_entities['CompSupplier']}}
@@ -228,7 +228,7 @@ describe 'complex entities workflow' do
228
228
 
229
229
  it 'handles the idmap correctly' do
230
230
  allow(connec_client).to receive(:batch).and_return(ActionDispatch::Response.new(201, {}, {results: []}.to_json, {}))
231
- allow_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:create_external_entity).and_return(connec_org1_ext_id)
231
+ allow_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:create_external_entity).and_return({'id' => connec_org1_ext_id})
232
232
  allow_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:update_external_entity).and_return(nil)
233
233
  expect{
234
234
  subject
@@ -267,14 +267,14 @@ describe 'complex entities workflow' do
267
267
  org1_idmap = Entities::SubEntities::CompOrganization.create_idmap(organization_id: organization.id, external_id: connec_org1_ext_id, external_entity: 'compsupplier')
268
268
  org2_idmap = Entities::SubEntities::CompOrganization.create_idmap(organization_id: organization.id, external_id: connec_org2_ext_id, external_entity: 'compcustomer')
269
269
  allow(Maestrano::Connector::Rails::IdMap).to receive(:create).and_return(org1_idmap, org2_idmap, cust_idmap)
270
- expect_any_instance_of(Entities::CustomerAndSupplier).to receive(:push_entities_to_external).with({'CompOrganization' => {'CompSupplier' => [{entity: mapped_connec_org1, idmap: org1_idmap}], 'CompCustomer' => [{entity: mapped_connec_org2, idmap: org2_idmap}]}})
271
- expect_any_instance_of(Entities::CustomerAndSupplier).to receive(:push_entities_to_connec).with({'CompCustomer' => {'CompOrganization' => [{entity: mapped_ext_customer, idmap: cust_idmap}]}, 'CompSupplier' => {'CompOrganization' => [{entity: mapped_ext_supplier, idmap: supplier_idmap}]}})
270
+ expect_any_instance_of(Entities::CustomerAndSupplier).to receive(:push_entities_to_external).with({'CompOrganization' => {'CompSupplier' => [{entity: mapped_connec_org1.with_indifferent_access, idmap: org1_idmap, id_refs_only_connec_entity: {}}], 'CompCustomer' => [{entity: mapped_connec_org2.with_indifferent_access, idmap: org2_idmap, id_refs_only_connec_entity: {}}]}})
271
+ expect_any_instance_of(Entities::CustomerAndSupplier).to receive(:push_entities_to_connec).with({'CompCustomer' => {'CompOrganization' => [{entity: mapped_ext_customer.with_indifferent_access, idmap: cust_idmap}]}, 'CompSupplier' => {'CompOrganization' => [{entity: mapped_ext_supplier.with_indifferent_access, idmap: supplier_idmap}]}})
272
272
  subject
273
273
  end
274
274
 
275
275
  it 'sends two objects to connec, two objects to external and send back one id to connec' do
276
- expect_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:create_external_entity).once
277
- expect_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:update_external_entity).once
276
+ expect_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:create_external_entity).once.with(mapped_connec_org1, 'CompSupplier').and_return({})
277
+ expect_any_instance_of(Entities::SubEntities::CompOrganization).to receive(:update_external_entity).once.with(mapped_connec_org2, connec_org2_ext_id, 'CompCustomer')
278
278
  expect(connec_client).to receive(:batch).exactly(3).times.and_return(ActionDispatch::Response.new(201, {}, {results: []}.to_json, {}), ActionDispatch::Response.new(200, {}, {results: []}.to_json, {}))
279
279
  subject
280
280
  end