maestrano-connector-rails 0.2.20 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -157
- data/VERSION +1 -1
- data/app/controllers/maestrano/connec_controller.rb +6 -6
- data/app/jobs/maestrano/connector/rails/push_to_connec_job.rb +6 -7
- data/app/jobs/maestrano/connector/rails/synchronization_job.rb +2 -0
- data/app/models/maestrano/connector/rails/concerns/complex_entity.rb +15 -15
- data/app/models/maestrano/connector/rails/concerns/entity.rb +156 -140
- data/app/models/maestrano/connector/rails/concerns/sub_entity_base.rb +54 -50
- data/lib/generators/connector/templates/complex_entity_example/contact.rb +4 -4
- data/lib/generators/connector/templates/complex_entity_example/contact_and_lead.rb +3 -3
- data/lib/generators/connector/templates/complex_entity_example/lead.rb +4 -4
- data/lib/generators/connector/templates/complex_entity_example/person.rb +4 -4
- data/lib/generators/connector/templates/entity.rb +2 -2
- data/lib/generators/connector/templates/example_entity.rb +5 -5
- data/maestrano-connector-rails.gemspec +3 -4
- data/spec/controllers/connec_controller_spec.rb +3 -3
- data/spec/jobs/push_to_connec_job_spec.rb +4 -4
- data/spec/jobs/syncrhonization_job_spec.rb +3 -1
- data/spec/models/complex_entity_spec.rb +25 -24
- data/spec/models/entity_spec.rb +123 -103
- data/spec/models/sub_entity_base_spec.rb +92 -86
- data/template/maestrano-connector-template.rb +4 -3
- metadata +2 -3
- data/lib/generators/connector/templates/contact_and_lead.rb +0 -55
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2f0083a436b601632884149aff3e8111b01ba1a6
|
4
|
+
data.tar.gz: c0e95181ea0b2a66b137e2ec6047ddd4bdc40f2c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41fceaf54ad78bdca9cbc7dd6dc07f5d22b67ad6ce532b5cf39d59aa57faccc57f3c657371b75a359570e58b648e3b59cfb0d2d271db4c13c1e8dd9f712e37fa
|
7
|
+
data.tar.gz: 639653b1337385bb1b60d45e160b2bb9db96308c4bb023dbfc1a86942e6fdabc78c923351884fed05f2fb83a938b38e4c76ad7bc385a1405a1bd9db69df306a5
|
data/README.md
CHANGED
@@ -8,162 +8,6 @@
|
|
8
8
|
</p>
|
9
9
|
|
10
10
|
Maestrano Connector is a Rails Engine that bootstraps the implementation of data syncrhonization between an external application API and the Maestrano ecosystem.
|
11
|
-
|
12
11
|
Maestrano Connector Integration is currently in closed beta. Want to know more? Send us an email to <contact@maestrano.com>.
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
1. [Getting Setup](#getting-setup)
|
17
|
-
2. [Getting Started](#getting-started)
|
18
|
-
* [Integration with Maestrano](#integration-with-maestrano)
|
19
|
-
* [Integration with the external application](#integration-with-the-external-application)
|
20
|
-
3. [Preparing synchronizations](#preparing-synchronizations)
|
21
|
-
* [External.rb](#external.rb)
|
22
|
-
* [Entity.rb](#entity.rb)
|
23
|
-
* [Mapping entities](#mapping-entities)
|
24
|
-
4. [Pages controllers and views](#pages-controllers-and-views)
|
25
|
-
5. [Complex entities](#complex-entities)
|
26
|
-
6. [Webhooks](#Webhooks)
|
27
|
-
|
28
|
-
- - -
|
29
|
-
|
30
|
-
## Getting Setup
|
31
|
-
Before integrating with us you will need to have your application registered on the Maestrano platform. Please refer to the online documentation we provide: https://maestrano.atlassian.net/wiki/display/CONNECAPIV2/Maestrano+Developers
|
32
|
-
|
33
|
-
## Getting Started
|
34
|
-
Create a new rails application using the connector template. The template works with both Ruby 2.2 and jRuby 9.0.4.0, you will be asked which one you want to use.
|
35
|
-
```console
|
36
|
-
rails new <project_name> -m https://raw.githubusercontent.com/Maestrano/maestrano-connector-rails/master/template/maestrano-connector-template.rb
|
37
|
-
```
|
38
|
-
|
39
|
-
If and only if you have an error in the template's rails generate step, you'll need to re-run the following command in your project folder:
|
40
|
-
```console
|
41
|
-
bundle
|
42
|
-
rails g connector:install
|
43
|
-
rake db:migrate
|
44
|
-
```
|
45
|
-
|
46
|
-
### Integration with Maestrano
|
47
|
-
|
48
|
-
First thing to do is to put your Connec!™ API keys in the config/application.yml:
|
49
|
-
```ruby
|
50
|
-
connec_api_id: 'API_ID'
|
51
|
-
connec_api_key: 'API_KEY'
|
52
|
-
```
|
53
|
-
|
54
|
-
The next thing you need to do is to set your configuration in config/initializers/maestrano.rb. You will need to define where your application will be publicly hosted:
|
55
|
-
```ruby
|
56
|
-
config.app.host = 'http://path_to_app'
|
57
|
-
```
|
58
|
-
The rest of the config has default values, so you can take a look but you don't really need to change anything else.
|
59
|
-
For a more detailed configuration, please refer to https://github.com/maestrano/maestrano-ruby#configuration
|
60
|
-
|
61
|
-
Please note that the connectors support multi-tenancy, so you may have to set up configuration for tenants other than the Maestrano platform (the default one).
|
62
|
-
|
63
|
-
These configuration are automatically retrieved by Maestrano via a metadata endpoint that is provided by the gem, so you're all setup as it is.
|
64
|
-
|
65
|
-
Time to test! If your launch your application (please make sure that you launch the application on the same path as the one in the config file). If you click on the 'Link your Maestrano account' link on your connector home page, you should be able to do a full SSO process with Maestrano.
|
66
|
-
|
67
|
-
### Integration with the external application
|
68
|
-
|
69
|
-
Now that you're all setup with Maestrano, it's time to take a look at the external application you are integrating with. Hopefully it has one or several gems for both the authentication process and the API calls. In any case, you'll need to take a look at their documentation.
|
70
|
-
|
71
|
-
You will probably have to request API keys and adds them to the application.yml alongside the Maestrano's ones.
|
72
|
-
|
73
|
-
The connector engine is thought to be able to use oauth authentication processes, and an oauth_controller is provided as an example. Please note that it is only an example and you will have to implements most of it, and to create the needed routes, and use them in the provided view.
|
74
|
-
|
75
|
-
If all went well, you should now be able to use the 'Link this company to...' link on the home page. Congrats!
|
76
|
-
|
77
|
-
## Preparing synchronizations
|
78
|
-
|
79
|
-
The aim of the connector is to perform synchronizations between Connec!™ and the external application, meaning fetching data on both ends, process them, and push the result to the relevant parties. The Connec!™ part and the synchronization process itself is handled by the engine, so all you have to do is to implements some methods to bridge the calls to the external application.
|
80
|
-
|
81
|
-
### external.rb
|
82
|
-
|
83
|
-
First file to look for is `models/maestrano/connector/rails/external.rb`. It contains two methods that you need to implement:
|
84
|
-
|
85
|
-
* external_name, which is used for logging purpose only, and should only return the name of the external application, e.g.
|
86
|
-
```ruby
|
87
|
-
def self.external_name
|
88
|
-
'This awesome CRM'
|
89
|
-
end
|
90
|
-
```
|
91
|
-
* get_client, which should return either the external application gem api client, or, in the worst case, a custom HTTParty client.
|
92
|
-
|
93
|
-
|
94
|
-
### entity.rb
|
95
|
-
|
96
|
-
The second important file is `models/maestrano/connector/rails/entity.rb`. It contains a method to declare the entities synchronizable by your connector (more on that later), some methods to retrieve and send data to the external application API, and lastly two methods to extract `id` and `timestamps` from the entity format sent by the external application.
|
97
|
-
|
98
|
-
The details of each methods are explained in the entity.rb file provided.
|
99
|
-
|
100
|
-
### Mapping entities
|
101
|
-
|
102
|
-
Now that you're all setup with both Connec!™ and the external application, it's time to decide which entities (contacts, accounts, events, ...) you want to synchronize. For each type of entity your connector will synchronize, you will need to create a class that inherits from `Maestrano::Connector::Rails::Entity`.
|
103
|
-
|
104
|
-
An example of such a class in provided in the models/entities/ folder, and demonstrates which methods you'll need to implements for each entity. The main thing to do is the mapping between the external entity and the Connec!™ entity. For the mapping, we use the hash_mapper gem (<https://github.com/ismasan/hash_mapper>).
|
105
|
-
|
106
|
-
This type of entity class enable one-to-one model correspondance. For more complex needs, please refer to the complex entity section below.
|
107
|
-
|
108
|
-
You'll find the connec API documentation here: <http://maestrano.github.io/connec/>, and should also refer to the external application API documentation.
|
109
|
-
|
110
|
-
Also don't forget that each entity your connector synchronize should be declared in the entity.rb class, and, because the synchronizable entities are stored in the local database for each organization, you'll need to create a migration for exisiting organization if you add an new entity.
|
111
|
-
|
112
|
-
#### Overriding methods
|
113
|
-
|
114
|
-
To fit each entity specific need, you can overide all methods define in the entity class, including those implemented by the engine.
|
115
|
-
|
116
|
-
In particular, you will probably need to override the mapping methods to realize reference between entities (this can't be done during the mapping because it requires the organization id).
|
117
|
-
|
118
|
-
For example:
|
119
|
-
```ruby
|
120
|
-
def map_to_connec(entity, organization)
|
121
|
-
if id = entity['AccountId']
|
122
|
-
idmap = Maestrano::Connector::Rails::IdMap.find_by(external_entity: 'account', external_id: id, organization_id: organization.id, connec_entity: 'organization')
|
123
|
-
entity['AccountId'] = idmap ? idmap.connec_id : ''
|
124
|
-
end
|
125
|
-
self.mapper_class.denormalize(entity)
|
126
|
-
end
|
127
|
-
```
|
128
|
-
|
129
|
-
### Triggering synchronizations
|
130
|
-
Performing the synchronization of all the linked organizations can be triggered by executing
|
131
|
-
```ruby
|
132
|
-
Maestrano::Connector::Rails::AllSynchronizationsJob
|
133
|
-
```
|
134
|
-
|
135
|
-
The synchronization of a specific organization can be performed by executing
|
136
|
-
```ruby
|
137
|
-
Maestrano::Connector::Rails::SynchronizationJob.perform_later(organization, {})
|
138
|
-
```
|
139
|
-
|
140
|
-
## Pages controllers and views
|
141
|
-
|
142
|
-
The home and admin pages views and controllers are provided as example, but you are free to customize them and the styling is left for you to do.
|
143
|
-
|
144
|
-
## Complex entities
|
145
|
-
|
146
|
-
For more complex correspondances, like one-to-many or many-to-many ones, you can use the complex entity workflow. To see how it works, you can run
|
147
|
-
```console
|
148
|
-
rails g connector:complex_entity
|
149
|
-
```
|
150
|
-
|
151
|
-
This will generate some example files demonstrating a one-to-many correspondance between Connec!™ person and external contact and lead data models.
|
152
|
-
|
153
|
-
The complex entities workflow uses two methods to pre-process data which you have to implements for each complex entity (see contact_and_lead.rb). They are called before the mapping step, and you can use them to perform any data model specific operations.
|
154
|
-
|
155
|
-
## Webhooks
|
156
|
-
|
157
|
-
Connec!™ issues webhooks each time an entity is created or updated. This allows real time integration from Connec!™ to the application you're integrating with. All you have to do is subscribe to the webhooks on the entities your interested in (in your Maestrano.rb file), everything else is magically handled by the gem.
|
158
|
-
|
159
|
-
If the application you're integrating with support webhooks, you can and should use them to allow a full real time integration. The gem provide a job to help you do that. It will perform the necessary checks, mappings and then push the entities to Connec!™. All you have to do is build a controller and config the necessary routes to catch the webhook, and call this job. For example:
|
160
|
-
```ruby
|
161
|
-
class ExternalWebhooksController < ApplicationController
|
162
|
-
def notification
|
163
|
-
organization = # find organization from webhook params
|
164
|
-
Maestrano::Connector::Rails::PushToConnecJob.perform_later(organization, params[:notif][:name], parmas[:notif][:objects])
|
165
|
-
end
|
166
|
-
end
|
167
|
-
```
|
168
|
-
|
169
|
-
If you have questions, please contact the technical team <developers@maestrano.com>.
|
13
|
+
You can find the documentation [here](https://maestrano.atlassian.net/wiki/display/CONNECAPIV2/Maestrano+connector+framework+-+rails). See also some generic documentation about integration with Maestrano [here](https://maestrano.atlassian.net/wiki/display/CONNECAPIV2/Maestrano+Developers).
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.3.0
|
@@ -16,7 +16,7 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
16
16
|
|
17
17
|
# Build expected input for consolidate_and_map_data
|
18
18
|
if entity_instance_hash[:is_complex]
|
19
|
-
mapped_entity = entity_instance.consolidate_and_map_data(Hash[ *entity_instance.connec_entities_names.collect{|name| name.
|
19
|
+
mapped_entity = entity_instance.consolidate_and_map_data(Hash[ *entity_instance.class.connec_entities_names.collect{|name| name.parameterize('_').pluralize == entity_name ? [name, [entity]] : [ name, []]}.flatten(1) ], Hash[ *entity_instance.class.external_entities_names.collect{|name| [ name, []]}.flatten(1) ], organization, {})
|
20
20
|
else
|
21
21
|
mapped_entity = entity_instance.consolidate_and_map_data([entity], [], organization, {})
|
22
22
|
end
|
@@ -44,11 +44,11 @@ class Maestrano::ConnecController < Maestrano::Rails::WebHookController
|
|
44
44
|
private
|
45
45
|
def find_entity_instance(entity_name)
|
46
46
|
Maestrano::Connector::Rails::Entity.entities_list.each do |entity_name_from_list|
|
47
|
-
|
48
|
-
if
|
49
|
-
return {instance:
|
50
|
-
elsif
|
51
|
-
return {instance:
|
47
|
+
clazz = "Entities::#{entity_name_from_list.singularize.titleize.split.join}".constantize
|
48
|
+
if clazz.methods.include?('connec_entities_names'.to_sym)
|
49
|
+
return {instance: clazz.new, is_complex: true, name: entity_name_from_list} if clazz.connec_entities_names.map{|n| n.parameterize('_').pluralize}.include?(entity_name)
|
50
|
+
elsif clazz.methods.include?('connec_entity_name'.to_sym)
|
51
|
+
return {instance: clazz.new, is_complex: false, name: entity_name_from_list} if clazz.normalized_connec_entity_name == entity_name
|
52
52
|
end
|
53
53
|
end
|
54
54
|
nil
|
@@ -12,9 +12,8 @@ module Maestrano::Connector::Rails
|
|
12
12
|
if entity_instance_hash = find_entity_instance(external_entity_name)
|
13
13
|
entity_instance = entity_instance_hash[:instance]
|
14
14
|
next unless organization.synchronized_entities[entity_instance_hash[:name].to_sym]
|
15
|
-
|
16
15
|
if entity_instance_hash[:is_complex]
|
17
|
-
mapped_entities = entity_instance.consolidate_and_map_data(Hash[ *entity_instance.connec_entities_names.collect{|name| [ name, []]}.flatten(1) ], Hash[ *entity_instance.external_entities_names.collect{|name| name == external_entity_name ? [name, entities] : [ name, []]}.flatten(1) ], organization, {})
|
16
|
+
mapped_entities = entity_instance.consolidate_and_map_data(Hash[ *entity_instance.class.connec_entities_names.collect{|name| [ name, []]}.flatten(1) ], Hash[ *entity_instance.class.external_entities_names.collect{|name| name == external_entity_name ? [name, entities] : [ name, []]}.flatten(1) ], organization, {})
|
18
17
|
else
|
19
18
|
mapped_entities = entity_instance.consolidate_and_map_data([], entities, organization, {})
|
20
19
|
end
|
@@ -29,11 +28,11 @@ module Maestrano::Connector::Rails
|
|
29
28
|
private
|
30
29
|
def find_entity_instance(entity_name)
|
31
30
|
Maestrano::Connector::Rails::Entity.entities_list.each do |entity_name_from_list|
|
32
|
-
|
33
|
-
if
|
34
|
-
return {instance:
|
35
|
-
elsif
|
36
|
-
return {instance:
|
31
|
+
clazz = "Entities::#{entity_name_from_list.singularize.titleize.split.join}".constantize
|
32
|
+
if clazz.methods.include?('external_entities_names'.to_sym)
|
33
|
+
return {instance: clazz.new, is_complex: true, name: entity_name_from_list} if clazz.external_entities_names.include?(entity_name)
|
34
|
+
elsif clazz.methods.include?('external_entity_name'.to_sym)
|
35
|
+
return {instance: clazz.new, is_complex: false, name: entity_name_from_list} if clazz.external_entity_name == entity_name
|
37
36
|
end
|
38
37
|
end
|
39
38
|
nil
|
@@ -49,11 +49,13 @@ module Maestrano::Connector::Rails
|
|
49
49
|
def sync_entity(entity_name, organization, connec_client, external_client, last_synchronization, opts)
|
50
50
|
entity_instance = "Entities::#{entity_name.titleize.split.join}".constantize.new
|
51
51
|
|
52
|
+
entity_instance.before_sync(connec_client, external_client, organization, opts)
|
52
53
|
external_entities = entity_instance.get_external_entities(external_client, last_synchronization, organization, opts)
|
53
54
|
connec_entities = entity_instance.get_connec_entities(connec_client, last_synchronization, organization, opts)
|
54
55
|
mapped_entities = entity_instance.consolidate_and_map_data(connec_entities, external_entities, organization, opts)
|
55
56
|
entity_instance.push_entities_to_external(external_client, mapped_entities[:connec_entities], organization)
|
56
57
|
entity_instance.push_entities_to_connec(connec_client, mapped_entities[:external_entities], organization)
|
58
|
+
entity_instance.after_sync(connec_client, external_client, organization, opts)
|
57
59
|
end
|
58
60
|
end
|
59
61
|
end
|
@@ -1,18 +1,18 @@
|
|
1
1
|
module Maestrano::Connector::Rails::Concerns::ComplexEntity
|
2
2
|
extend ActiveSupport::Concern
|
3
3
|
|
4
|
-
@@external_name = Maestrano::Connector::Rails::External.external_name
|
5
|
-
|
6
4
|
# -------------------------------------------------------------
|
7
5
|
# Complex specific methods
|
8
6
|
# Those methods needs to be implemented in each complex entity
|
9
7
|
# -------------------------------------------------------------
|
10
|
-
|
11
|
-
|
12
|
-
|
8
|
+
module ClassMethods
|
9
|
+
def connec_entities_names
|
10
|
+
raise "Not implemented"
|
11
|
+
end
|
13
12
|
|
14
|
-
|
15
|
-
|
13
|
+
def external_entities_names
|
14
|
+
raise "Not implemented"
|
15
|
+
end
|
16
16
|
end
|
17
17
|
|
18
18
|
# input : {
|
@@ -53,18 +53,18 @@ module Maestrano::Connector::Rails::Concerns::ComplexEntity
|
|
53
53
|
# General methods
|
54
54
|
# -------------------------------------------------------------
|
55
55
|
def map_to_external_with_idmap(entity, organization, external_entity_name, sub_entity_instance)
|
56
|
-
idmap = sub_entity_instance.find_idmap({connec_id: entity['id'], external_entity: external_entity_name, organization_id: organization.id})
|
56
|
+
idmap = sub_entity_instance.class.find_idmap({connec_id: entity['id'], external_entity: external_entity_name, organization_id: organization.id})
|
57
57
|
|
58
58
|
if idmap
|
59
|
-
idmap.update(name: sub_entity_instance.object_name_from_connec_entity_hash(entity))
|
59
|
+
idmap.update(name: sub_entity_instance.class.object_name_from_connec_entity_hash(entity))
|
60
60
|
if (!idmap.to_external) || idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at']
|
61
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{sub_entity_instance.entity_name} : #{entity}")
|
61
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{sub_entity_instance.class.entity_name} : #{entity}")
|
62
62
|
nil
|
63
63
|
else
|
64
64
|
{entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: idmap}
|
65
65
|
end
|
66
66
|
else
|
67
|
-
{entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: sub_entity_instance.create_idmap_from_connec_entity(entity, external_entity_name, organization)}
|
67
|
+
{entity: sub_entity_instance.map_to(external_entity_name, entity, organization), idmap: sub_entity_instance.class.create_idmap_from_connec_entity(entity, external_entity_name, organization)}
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
@@ -100,20 +100,20 @@ module Maestrano::Connector::Rails::Concerns::ComplexEntity
|
|
100
100
|
sub_entity_instance = "Entities::SubEntities::#{external_entity_name.titleize.split.join}".constantize.new
|
101
101
|
|
102
102
|
entities.map!{|entity|
|
103
|
-
idmap = sub_entity_instance.find_idmap(external_id: sub_entity_instance.
|
103
|
+
idmap = sub_entity_instance.class.find_idmap(external_id: sub_entity_instance.class.id_from_external_entity_hash(entity), connec_entity: connec_entity_name, organization_id: organization.id)
|
104
104
|
|
105
105
|
# No idmap: creating one, nothing else to do
|
106
106
|
if idmap
|
107
|
-
idmap.update(name: sub_entity_instance.object_name_from_external_entity_hash(entity))
|
107
|
+
idmap.update(name: sub_entity_instance.class.object_name_from_external_entity_hash(entity))
|
108
108
|
else
|
109
|
-
next {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: sub_entity_instance.create_idmap_from_external_entity(entity, connec_entity_name, organization)}
|
109
|
+
next {entity: sub_entity_instance.map_to(connec_entity_name, entity, organization), idmap: sub_entity_instance.class.create_idmap_from_external_entity(entity, connec_entity_name, organization)}
|
110
110
|
end
|
111
111
|
|
112
112
|
# Not pushing entity to Connec!
|
113
113
|
next nil unless idmap.to_connec
|
114
114
|
|
115
115
|
# Entity has not been modified since its last push to connec!
|
116
|
-
next nil if Maestrano::Connector::Rails::Entity.not_modified_since_last_push_to_connec(idmap, entity, sub_entity_instance, organization)
|
116
|
+
next nil if Maestrano::Connector::Rails::Entity.not_modified_since_last_push_to_connec?(idmap, entity, sub_entity_instance, organization)
|
117
117
|
|
118
118
|
# Check for conflict with entities from connec!
|
119
119
|
equivalent_connec_entities = modeled_connec_entities[connec_entity_name][external_entity_name] || []
|
@@ -8,143 +8,191 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
8
8
|
def entities_list
|
9
9
|
raise "Not implemented"
|
10
10
|
end
|
11
|
-
end
|
12
11
|
|
13
|
-
|
12
|
+
# ----------------------------------------------
|
13
|
+
# IdMap methods
|
14
|
+
# ----------------------------------------------
|
15
|
+
def names_hash
|
16
|
+
{
|
17
|
+
connec_entity: connec_entity_name.downcase,
|
18
|
+
external_entity: external_entity_name.downcase
|
19
|
+
}
|
20
|
+
end
|
21
|
+
|
22
|
+
def find_or_create_idmap(organization_and_id)
|
23
|
+
Maestrano::Connector::Rails::IdMap.find_or_create_by(names_hash.merge(organization_and_id))
|
24
|
+
end
|
25
|
+
|
26
|
+
# organization_and_id can be either:
|
27
|
+
# * {connec_id: 'id', organization_id: 'id'}
|
28
|
+
# * {external_id: 'id', organization_id: 'id'}
|
29
|
+
# Needs to include either connec_entity or external_entity for complex entities
|
30
|
+
def find_idmap(organization_and_id)
|
31
|
+
Maestrano::Connector::Rails::IdMap.find_by(names_hash.merge(organization_and_id))
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_idmap_from_external_entity(entity, organization)
|
35
|
+
h = names_hash.merge({
|
36
|
+
external_id: id_from_external_entity_hash(entity),
|
37
|
+
name: object_name_from_external_entity_hash(entity),
|
38
|
+
organization_id: organization.id
|
39
|
+
})
|
40
|
+
Maestrano::Connector::Rails::IdMap.create(h)
|
41
|
+
end
|
42
|
+
|
43
|
+
def create_idmap_from_connec_entity(entity, organization)
|
44
|
+
h = names_hash.merge({
|
45
|
+
connec_id: entity['id'],
|
46
|
+
name: object_name_from_connec_entity_hash(entity),
|
47
|
+
organization_id: organization.id
|
48
|
+
})
|
49
|
+
Maestrano::Connector::Rails::IdMap.create(h)
|
50
|
+
end
|
51
|
+
|
52
|
+
# ----------------------------------------------
|
53
|
+
# Connec! methods
|
54
|
+
# ----------------------------------------------
|
55
|
+
def normalized_connec_entity_name
|
56
|
+
normalize_connec_entity_name(connec_entity_name)
|
57
|
+
end
|
58
|
+
|
59
|
+
def normalize_connec_entity_name(name)
|
60
|
+
if singleton?
|
61
|
+
name.parameterize('_')
|
62
|
+
else
|
63
|
+
name.parameterize('_').pluralize
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
# ----------------------------------------------
|
68
|
+
# External methods
|
69
|
+
# ----------------------------------------------
|
70
|
+
def id_from_external_entity_hash(entity)
|
71
|
+
raise "Not implemented"
|
72
|
+
end
|
73
|
+
|
74
|
+
def last_update_date_from_external_entity_hash(entity)
|
75
|
+
raise "Not implemented"
|
76
|
+
end
|
77
|
+
|
78
|
+
# ----------------------------------------------
|
79
|
+
# Entity specific methods
|
80
|
+
# Those methods need to be define in each entity
|
81
|
+
# ----------------------------------------------
|
82
|
+
# Is this resource a singleton (in Connec!)?
|
83
|
+
def singleton?
|
84
|
+
false
|
85
|
+
end
|
86
|
+
|
87
|
+
# Entity name in Connec!
|
88
|
+
def connec_entity_name
|
89
|
+
raise "Not implemented"
|
90
|
+
end
|
91
|
+
|
92
|
+
# Entity name in external system
|
93
|
+
def external_entity_name
|
94
|
+
raise "Not implemented"
|
95
|
+
end
|
96
|
+
|
97
|
+
# Entity Mapper Class
|
98
|
+
def mapper_class
|
99
|
+
raise "Not implemented"
|
100
|
+
end
|
101
|
+
|
102
|
+
# Return a string representing the object from a connec! entity hash
|
103
|
+
def object_name_from_connec_entity_hash(entity)
|
104
|
+
raise "Not implemented"
|
105
|
+
end
|
106
|
+
|
107
|
+
# Return a string representing the object from an external entity hash
|
108
|
+
def object_name_from_external_entity_hash(entity)
|
109
|
+
raise "Not implemented"
|
110
|
+
end
|
111
|
+
end
|
14
112
|
|
15
113
|
# ----------------------------------------------
|
16
114
|
# Mapper methods
|
17
115
|
# ----------------------------------------------
|
18
116
|
# Map a Connec! entity to the external format
|
19
117
|
def map_to_external(entity, organization)
|
20
|
-
mapper_class.normalize(entity)
|
118
|
+
self.class.mapper_class.normalize(entity)
|
21
119
|
end
|
22
120
|
|
23
121
|
# Map an external entity to Connec! format
|
24
122
|
def map_to_connec(entity, organization)
|
25
|
-
mapper_class.denormalize(entity)
|
123
|
+
self.class.mapper_class.denormalize(entity)
|
26
124
|
end
|
27
125
|
|
28
|
-
# ----------------------------------------------
|
29
|
-
# IdMap methods
|
30
|
-
# ----------------------------------------------
|
31
|
-
def names_hash
|
32
|
-
{
|
33
|
-
connec_entity: connec_entity_name.downcase,
|
34
|
-
external_entity: external_entity_name.downcase
|
35
|
-
}
|
36
|
-
end
|
37
|
-
|
38
|
-
def find_or_create_idmap(organization_and_id)
|
39
|
-
Maestrano::Connector::Rails::IdMap.find_or_create_by(names_hash.merge(organization_and_id))
|
40
|
-
end
|
41
|
-
|
42
|
-
# organization_and_id can be either:
|
43
|
-
# * {connec_id: 'id', organization_id: 'id'}
|
44
|
-
# * {external_id: 'id', organization_id: 'id'}
|
45
|
-
# Needs to include either connec_entity or external_entity for complex entities
|
46
|
-
def find_idmap(organization_and_id)
|
47
|
-
Maestrano::Connector::Rails::IdMap.find_by(names_hash.merge(organization_and_id))
|
48
|
-
end
|
49
|
-
|
50
|
-
def create_idmap_from_external_entity(entity, organization)
|
51
|
-
h = names_hash.merge({
|
52
|
-
external_id: get_id_from_external_entity_hash(entity),
|
53
|
-
name: object_name_from_external_entity_hash(entity),
|
54
|
-
organization_id: organization.id
|
55
|
-
})
|
56
|
-
Maestrano::Connector::Rails::IdMap.create(h)
|
57
|
-
end
|
58
|
-
|
59
|
-
def create_idmap_from_connec_entity(entity, organization)
|
60
|
-
h = names_hash.merge({
|
61
|
-
connec_id: entity['id'],
|
62
|
-
name: object_name_from_connec_entity_hash(entity),
|
63
|
-
organization_id: organization.id
|
64
|
-
})
|
65
|
-
Maestrano::Connector::Rails::IdMap.create(h)
|
66
|
-
end
|
67
126
|
# ----------------------------------------------
|
68
127
|
# Connec! methods
|
69
128
|
# ----------------------------------------------
|
70
|
-
def normalized_connec_entity_name
|
71
|
-
normalize_connec_entity_name(connec_entity_name)
|
72
|
-
end
|
73
|
-
|
74
|
-
def normalize_connec_entity_name(connec_entity_name)
|
75
|
-
if singleton?
|
76
|
-
connec_entity_name.downcase
|
77
|
-
else
|
78
|
-
connec_entity_name.downcase.pluralize
|
79
|
-
end
|
80
|
-
end
|
81
|
-
|
82
129
|
def get_connec_entities(client, last_synchronization, organization, opts={})
|
83
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching Connec! #{connec_entity_name}")
|
130
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching Connec! #{self.class.connec_entity_name}")
|
84
131
|
|
85
132
|
entities = []
|
86
133
|
|
87
134
|
# Fetch first page
|
88
135
|
if last_synchronization.blank? || opts[:full_sync]
|
89
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{connec_entity_name}, fetching all data")
|
90
|
-
response = client.get("/#{normalized_connec_entity_name}")
|
136
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{self.class.connec_entity_name}, fetching all data")
|
137
|
+
response = client.get("/#{self.class.normalized_connec_entity_name}")
|
91
138
|
else
|
92
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{connec_entity_name}, fetching data since #{last_synchronization.updated_at.iso8601}")
|
139
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "entity=#{self.class.connec_entity_name}, fetching data since #{last_synchronization.updated_at.iso8601}")
|
93
140
|
query_param = URI.encode("$filter=updated_at gt '#{last_synchronization.updated_at.iso8601}'")
|
94
|
-
response = client.get("/#{normalized_connec_entity_name}?#{query_param}")
|
141
|
+
response = client.get("/#{self.class.normalized_connec_entity_name}?#{query_param}")
|
95
142
|
end
|
96
|
-
raise "No data received from Connec! when trying to fetch #{connec_entity_name.pluralize}" unless response
|
143
|
+
raise "No data received from Connec! when trying to fetch #{self.class.connec_entity_name.pluralize}" unless response
|
97
144
|
|
98
145
|
response_hash = JSON.parse(response.body)
|
99
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received first page entity=#{connec_entity_name}, response=#{response.body}")
|
100
|
-
if response_hash["#{normalized_connec_entity_name}"]
|
101
|
-
entities << response_hash["#{normalized_connec_entity_name}"]
|
146
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received first page entity=#{self.class.connec_entity_name}, response=#{response.body}")
|
147
|
+
if response_hash["#{self.class.normalized_connec_entity_name}"]
|
148
|
+
entities << response_hash["#{self.class.normalized_connec_entity_name}"]
|
102
149
|
else
|
103
|
-
raise "Received unrecognized Connec! data when trying to fetch #{connec_entity_name.pluralize}"
|
150
|
+
raise "Received unrecognized Connec! data when trying to fetch #{self.class.connec_entity_name.pluralize}"
|
104
151
|
end
|
105
152
|
|
106
153
|
# Fetch subsequent pages
|
107
154
|
while response_hash['pagination'] && response_hash['pagination']['next']
|
108
155
|
# ugly way to convert https://api-connec/api/v2/group_id/organizations?next_page_params to /organizations?next_page_params
|
109
|
-
next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{normalized_connec_entity_name}/, normalized_connec_entity_name)
|
156
|
+
next_page = response_hash['pagination']['next'].gsub(/^(.*)\/#{self.class.normalized_connec_entity_name}/, self.class.normalized_connec_entity_name)
|
110
157
|
response = client.get(next_page)
|
111
158
|
|
112
|
-
raise "No data received from Connec! when trying to fetch subsequent page of #{connec_entity_name.pluralize}" unless response
|
113
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received next page entity=#{connec_entity_name}, response=#{response.body}")
|
159
|
+
raise "No data received from Connec! when trying to fetch subsequent page of #{self.class.connec_entity_name.pluralize}" unless response
|
160
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('debug', organization, "received next page entity=#{self.class.connec_entity_name}, response=#{response.body}")
|
114
161
|
|
115
162
|
response_hash = JSON.parse(response.body)
|
116
|
-
if response_hash["#{normalized_connec_entity_name}"]
|
117
|
-
entities << response_hash["#{normalized_connec_entity_name}"]
|
163
|
+
if response_hash["#{self.class.normalized_connec_entity_name}"]
|
164
|
+
entities << response_hash["#{self.class.normalized_connec_entity_name}"]
|
118
165
|
else
|
119
|
-
raise "Received unrecognized Connec! data when trying to fetch subsequent page of #{connec_entity_name.pluralize}"
|
166
|
+
raise "Received unrecognized Connec! data when trying to fetch subsequent page of #{self.class.connec_entity_name.pluralize}"
|
120
167
|
end
|
121
168
|
end
|
122
169
|
|
123
170
|
entities = entities.flatten
|
124
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received data: Source=Connec!, Entity=#{connec_entity_name}, Data=#{entities}")
|
171
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Received data: Source=Connec!, Entity=#{self.class.connec_entity_name}, Data=#{entities}")
|
125
172
|
entities
|
126
173
|
end
|
127
174
|
|
128
175
|
def push_entities_to_connec(connec_client, mapped_external_entities_with_idmaps, organization)
|
129
|
-
push_entities_to_connec_to(connec_client, mapped_external_entities_with_idmaps, connec_entity_name, organization)
|
176
|
+
push_entities_to_connec_to(connec_client, mapped_external_entities_with_idmaps, self.class.connec_entity_name, organization)
|
130
177
|
end
|
131
178
|
|
132
179
|
def push_entities_to_connec_to(connec_client, mapped_external_entities_with_idmaps, connec_entity_name, organization)
|
133
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{
|
180
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending #{Maestrano::Connector::Rails::External.external_name} #{self.class.external_entity_name.pluralize} to Connec! #{connec_entity_name.pluralize}")
|
134
181
|
mapped_external_entities_with_idmaps.each do |mapped_external_entity_with_idmap|
|
135
182
|
external_entity = mapped_external_entity_with_idmap[:entity]
|
136
183
|
idmap = mapped_external_entity_with_idmap[:idmap]
|
137
184
|
|
138
185
|
begin
|
139
186
|
if idmap.connec_id.blank?
|
140
|
-
connec_entity = create_connec_entity(connec_client, external_entity, normalize_connec_entity_name(connec_entity_name), organization)
|
141
|
-
idmap.update_attributes(connec_id: connec_entity['id'],
|
187
|
+
connec_entity = create_connec_entity(connec_client, external_entity, self.class.normalize_connec_entity_name(connec_entity_name), organization)
|
188
|
+
idmap.update_attributes(connec_id: connec_entity['id'], last_push_to_connec: Time.now, message: nil)
|
142
189
|
else
|
143
|
-
connec_entity = update_connec_entity(connec_client, external_entity, idmap.connec_id, normalize_connec_entity_name(connec_entity_name), organization)
|
190
|
+
connec_entity = update_connec_entity(connec_client, external_entity, idmap.connec_id, self.class.normalize_connec_entity_name(connec_entity_name), organization)
|
144
191
|
idmap.update_attributes(last_push_to_connec: Time.now, message: nil)
|
145
192
|
end
|
146
193
|
rescue => e
|
147
194
|
# Store Connec! error if any
|
195
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('error', organization, "Error while pushing to Connec!: #{e}")
|
148
196
|
idmap.update_attributes(message: e.message)
|
149
197
|
end
|
150
198
|
end
|
@@ -167,18 +215,18 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
167
215
|
end
|
168
216
|
|
169
217
|
def map_to_external_with_idmap(entity, organization)
|
170
|
-
idmap = find_idmap({connec_id: entity['id'], organization_id: organization.id})
|
218
|
+
idmap = self.class.find_idmap({connec_id: entity['id'], organization_id: organization.id})
|
171
219
|
|
172
220
|
if idmap
|
173
|
-
idmap.update(name: object_name_from_connec_entity_hash(entity))
|
221
|
+
idmap.update(name: self.class.object_name_from_connec_entity_hash(entity))
|
174
222
|
if (!idmap.to_external) || (idmap.last_push_to_external && idmap.last_push_to_external > entity['updated_at'])
|
175
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{connec_entity_name} : #{entity}")
|
223
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard Connec! #{self.class.connec_entity_name} : #{entity}")
|
176
224
|
nil
|
177
225
|
else
|
178
226
|
{entity: map_to_external(entity, organization), idmap: idmap}
|
179
227
|
end
|
180
228
|
else
|
181
|
-
{entity: map_to_external(entity, organization), idmap: create_idmap_from_connec_entity(entity, organization)}
|
229
|
+
{entity: map_to_external(entity, organization), idmap: self.class.create_idmap_from_connec_entity(entity, organization)}
|
182
230
|
end
|
183
231
|
end
|
184
232
|
|
@@ -186,16 +234,16 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
186
234
|
# External methods
|
187
235
|
# ----------------------------------------------
|
188
236
|
def get_external_entities(client, last_synchronization, organization, opts={})
|
189
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching #{
|
237
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Fetching #{Maestrano::Connector::Rails::External.external_name} #{self.class.external_entity_name.pluralize}")
|
190
238
|
raise "Not implemented"
|
191
239
|
end
|
192
240
|
|
193
241
|
def push_entities_to_external(external_client, mapped_connec_entities_with_idmaps, organization)
|
194
|
-
push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps, external_entity_name, organization)
|
242
|
+
push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps, self.class.external_entity_name, organization)
|
195
243
|
end
|
196
244
|
|
197
245
|
def push_entities_to_external_to(external_client, mapped_connec_entities_with_idmaps, external_entity_name, organization)
|
198
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending Connec! #{connec_entity_name.pluralize} to #{
|
246
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending Connec! #{self.class.connec_entity_name.pluralize} to #{Maestrano::Connector::Rails::External.external_name} #{external_entity_name.pluralize}")
|
199
247
|
mapped_connec_entities_with_idmaps.each do |mapped_connec_entity_with_idmap|
|
200
248
|
push_entity_to_external(external_client, mapped_connec_entity_with_idmap, external_entity_name, organization)
|
201
249
|
end
|
@@ -208,35 +256,27 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
208
256
|
begin
|
209
257
|
if idmap.external_id.blank?
|
210
258
|
external_id = create_external_entity(external_client, connec_entity, external_entity_name, organization)
|
211
|
-
idmap.update_attributes(external_id: external_id,
|
259
|
+
idmap.update_attributes(external_id: external_id, last_push_to_external: Time.now, message: nil)
|
212
260
|
else
|
213
261
|
update_external_entity(external_client, connec_entity, idmap.external_id, external_entity_name, organization)
|
214
262
|
idmap.update_attributes(last_push_to_external: Time.now, message: nil)
|
215
263
|
end
|
216
264
|
rescue => e
|
217
265
|
# Store External error
|
266
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('error', organization, "Error while pushing to #{Maestrano::Connector::Rails::External.external_name}: #{e}")
|
218
267
|
idmap.update_attributes(message: e.message)
|
219
268
|
end
|
220
269
|
end
|
221
270
|
|
222
271
|
def create_external_entity(client, mapped_connec_entity, external_entity_name, organization)
|
223
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending create #{external_entity_name}: #{mapped_connec_entity} to #{
|
272
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending create #{external_entity_name}: #{mapped_connec_entity} to #{Maestrano::Connector::Rails::External.external_name}")
|
224
273
|
raise "Not implemented"
|
225
274
|
end
|
226
275
|
|
227
276
|
def update_external_entity(client, mapped_connec_entity, external_id, external_entity_name, organization)
|
228
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending update #{external_entity_name} (id=#{external_id}): #{mapped_connec_entity} to #{
|
277
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Sending update #{external_entity_name} (id=#{external_id}): #{mapped_connec_entity} to #{Maestrano::Connector::Rails::External.external_name}")
|
229
278
|
raise "Not implemented"
|
230
279
|
end
|
231
|
-
|
232
|
-
def get_id_from_external_entity_hash(entity)
|
233
|
-
raise "Not implemented"
|
234
|
-
end
|
235
|
-
|
236
|
-
def get_last_update_date_from_external_entity_hash(entity)
|
237
|
-
raise "Not implemented"
|
238
|
-
end
|
239
|
-
|
240
280
|
# ----------------------------------------------
|
241
281
|
# General methods
|
242
282
|
# ----------------------------------------------
|
@@ -245,25 +285,25 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
245
285
|
# * Maps not discarded entities and associates them with their idmap, or create one if there isn't any
|
246
286
|
# * Return a hash {connec_entities: [], external_entities: []}
|
247
287
|
def consolidate_and_map_data(connec_entities, external_entities, organization, opts={})
|
248
|
-
return consolidate_and_map_singleton(connec_entities, external_entities, organization, opts) if singleton?
|
288
|
+
return consolidate_and_map_singleton(connec_entities, external_entities, organization, opts) if self.class.singleton?
|
249
289
|
|
250
290
|
mapped_external_entities = external_entities.map{|entity|
|
251
|
-
idmap = find_idmap({external_id:
|
291
|
+
idmap = self.class.find_idmap({external_id: self.class.id_from_external_entity_hash(entity), organization_id: organization.id})
|
252
292
|
# No idmap: creating one, nothing else to do
|
253
293
|
if idmap
|
254
|
-
idmap.update(name: object_name_from_external_entity_hash(entity))
|
294
|
+
idmap.update(name: self.class.object_name_from_external_entity_hash(entity))
|
255
295
|
else
|
256
|
-
next {entity: map_to_connec(entity, organization), idmap: create_idmap_from_external_entity(entity, organization)}
|
296
|
+
next {entity: map_to_connec(entity, organization), idmap: self.class.create_idmap_from_external_entity(entity, organization)}
|
257
297
|
end
|
258
298
|
|
259
299
|
# Not pushing entity to Connec!
|
260
300
|
next nil unless idmap.to_connec
|
261
301
|
|
262
302
|
# Entity has not been modified since its last push to connec!
|
263
|
-
next nil if self.class.not_modified_since_last_push_to_connec(idmap, entity, self, organization)
|
303
|
+
next nil if self.class.not_modified_since_last_push_to_connec?(idmap, entity, self, organization)
|
264
304
|
|
265
305
|
# Check for conflict with entities from connec!
|
266
|
-
self.class.solve_conflict(entity, self, connec_entities, connec_entity_name, idmap, organization, opts)
|
306
|
+
self.class.solve_conflict(entity, self, connec_entities, self.class.connec_entity_name, idmap, organization, opts)
|
267
307
|
}
|
268
308
|
mapped_external_entities.compact!
|
269
309
|
|
@@ -278,7 +318,7 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
278
318
|
def consolidate_and_map_singleton(connec_entities, external_entities, organization, opts={})
|
279
319
|
return {connec_entities: [], external_entities: []} if external_entities.empty? && connec_entities.empty?
|
280
320
|
|
281
|
-
idmap = find_or_create_idmap({organization_id: organization.id})
|
321
|
+
idmap = self.class.find_or_create_idmap({organization_id: organization.id})
|
282
322
|
|
283
323
|
if external_entities.empty?
|
284
324
|
keep_external = false
|
@@ -290,61 +330,37 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
290
330
|
keep_external = self.class.is_external_more_recent?(connec_entities.first, external_entities.first, self)
|
291
331
|
end
|
292
332
|
if keep_external
|
293
|
-
idmap.update(external_id:
|
333
|
+
idmap.update(external_id: self.class.id_from_external_entity_hash(external_entities.first), name: self.class.object_name_from_external_entity_hash(external_entities.first))
|
294
334
|
return {connec_entities: [], external_entities: [{entity: map_to_connec(external_entities.first, organization), idmap: idmap}]}
|
295
335
|
else
|
296
|
-
idmap.update(connec_id: connec_entities.first['id'], name: object_name_from_connec_entity_hash(connec_entities.first))
|
336
|
+
idmap.update(connec_id: connec_entities.first['id'], name: self.class.object_name_from_connec_entity_hash(connec_entities.first))
|
297
337
|
return {connec_entities: [{entity: map_to_external(connec_entities.first, organization), idmap: idmap}], external_entities: []}
|
298
338
|
end
|
299
339
|
end
|
300
340
|
|
301
341
|
# ----------------------------------------------
|
302
|
-
#
|
303
|
-
# Those methods need to be define in each entity
|
342
|
+
# After and before sync
|
304
343
|
# ----------------------------------------------
|
305
|
-
|
306
|
-
|
307
|
-
false
|
344
|
+
def before_sync(connec_client, external_client, organization)
|
345
|
+
# Does nothing by default
|
308
346
|
end
|
309
347
|
|
310
|
-
|
311
|
-
|
312
|
-
raise "Not implemented"
|
348
|
+
def after_sync(connec_client, external_client, organization)
|
349
|
+
# Does nothing by default
|
313
350
|
end
|
314
351
|
|
315
|
-
# Entity name in external system
|
316
|
-
def external_entity_name
|
317
|
-
raise "Not implemented"
|
318
|
-
end
|
319
|
-
|
320
|
-
# Entity Mapper Class
|
321
|
-
def mapper_class
|
322
|
-
raise "Not implemented"
|
323
|
-
end
|
324
|
-
|
325
|
-
# Return a string representing the object from a connec! entity hash
|
326
|
-
def object_name_from_connec_entity_hash(entity)
|
327
|
-
raise "Not implemented"
|
328
|
-
end
|
329
|
-
|
330
|
-
# Return a string representing the object from an external entity hash
|
331
|
-
def object_name_from_external_entity_hash(entity)
|
332
|
-
raise "Not implemented"
|
333
|
-
end
|
334
|
-
|
335
|
-
|
336
352
|
# ----------------------------------------------
|
337
353
|
# Internal helper methods
|
338
354
|
# ----------------------------------------------
|
339
355
|
module ClassMethods
|
340
|
-
def not_modified_since_last_push_to_connec(idmap, entity, entity_instance, organization)
|
341
|
-
result = idmap.last_push_to_connec && idmap.last_push_to_connec > entity_instance.
|
342
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard #{entity_instance.external_entity_name} : #{entity}") if result
|
356
|
+
def not_modified_since_last_push_to_connec?(idmap, entity, entity_instance, organization)
|
357
|
+
result = idmap.last_push_to_connec && idmap.last_push_to_connec > entity_instance.class.last_update_date_from_external_entity_hash(entity)
|
358
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Discard #{Maestrano::Connector::Rails::External::external_name} #{entity_instance.class.external_entity_name} : #{entity}") if result
|
343
359
|
result
|
344
360
|
end
|
345
361
|
|
346
362
|
def is_external_more_recent?(connec_entity, external_entity, entity_instance)
|
347
|
-
connec_entity['updated_at'] < entity_instance.
|
363
|
+
connec_entity['updated_at'] < entity_instance.class.last_update_date_from_external_entity_hash(external_entity)
|
348
364
|
end
|
349
365
|
|
350
366
|
def solve_conflict(external_entity, entity_instance, connec_entities, connec_entity_name, idmap, organization, opts)
|
@@ -357,11 +373,11 @@ module Maestrano::Connector::Rails::Concerns::Entity
|
|
357
373
|
end
|
358
374
|
|
359
375
|
if keep_external
|
360
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{entity_instance.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from external kept")
|
376
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{Maestrano::Connector::Rails::External::external_name} #{entity_instance.class.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from external kept")
|
361
377
|
connec_entities.delete(connec_entity)
|
362
378
|
entity_instance.map_external_entity_with_idmap(external_entity, connec_entity_name, idmap, organization)
|
363
379
|
else
|
364
|
-
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{entity_instance.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
380
|
+
Maestrano::Connector::Rails::ConnectorLogger.log('info', organization, "Conflict between #{Maestrano::Connector::Rails::External::external_name} #{entity_instance.class.external_entity_name} #{external_entity} and Connec! #{connec_entity_name} #{connec_entity}. Entity from Connec! kept")
|
365
381
|
nil
|
366
382
|
end
|
367
383
|
|