infopark_webcrm_sdk 1.0.0.rc3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/LICENSE +840 -0
- data/README.md +113 -0
- data/UPGRADE.md +507 -0
- data/config/ca-bundle.crt +4484 -0
- data/lib/crm/account.rb +17 -0
- data/lib/crm/activity.rb +143 -0
- data/lib/crm/collection.rb +41 -0
- data/lib/crm/contact.rb +121 -0
- data/lib/crm/core/attachment_store.rb +122 -0
- data/lib/crm/core/basic_resource.rb +68 -0
- data/lib/crm/core/configuration.rb +65 -0
- data/lib/crm/core/connection_manager.rb +98 -0
- data/lib/crm/core/item_enumerator.rb +61 -0
- data/lib/crm/core/log_subscriber.rb +41 -0
- data/lib/crm/core/mixins/attribute_provider.rb +135 -0
- data/lib/crm/core/mixins/change_loggable.rb +98 -0
- data/lib/crm/core/mixins/findable.rb +28 -0
- data/lib/crm/core/mixins/inspectable.rb +27 -0
- data/lib/crm/core/mixins/merge_and_deletable.rb +17 -0
- data/lib/crm/core/mixins/modifiable.rb +102 -0
- data/lib/crm/core/mixins/searchable.rb +88 -0
- data/lib/crm/core/mixins.rb +6 -0
- data/lib/crm/core/rest_api.rb +148 -0
- data/lib/crm/core/search_configurator.rb +207 -0
- data/lib/crm/core.rb +6 -0
- data/lib/crm/errors.rb +169 -0
- data/lib/crm/event.rb +17 -0
- data/lib/crm/event_contact.rb +16 -0
- data/lib/crm/mailing.rb +111 -0
- data/lib/crm/template_set.rb +81 -0
- data/lib/crm/type.rb +78 -0
- data/lib/crm.rb +154 -0
- data/lib/infopark_webcrm_sdk.rb +1 -0
- metadata +149 -0
data/README.md
ADDED
@@ -0,0 +1,113 @@
|
|
1
|
+
# Infopark WebCRM SDK
|
2
|
+
|
3
|
+
[![Build Status](https://magnum.travis-ci.com/infopark/webcrm_sdk.svg?token=iixzKo9dcgfko6CA7rmm&branch=dev)](https://magnum.travis-ci.com/infopark/webcrm_sdk)
|
4
|
+
|
5
|
+
[Infopark WebCRM](https://infopark.com/) is a cloud-based CRM.
|
6
|
+
The Infopark WebCRM SDK makes CRM content available to your Ruby application.
|
7
|
+
It is a client of the Infopark WebCRM REST API v2.
|
8
|
+
|
9
|
+
This SDK lets you access and manipulate accounts and contacts, for example, perform searches, etc.
|
10
|
+
|
11
|
+
## Installation
|
12
|
+
|
13
|
+
Add `infopark_webcrm_sdk` to your `Gemfile`:
|
14
|
+
|
15
|
+
gem 'infopark_webcrm_sdk'
|
16
|
+
|
17
|
+
Install the gem with [Bundler](http://bundler.io/):
|
18
|
+
|
19
|
+
bundle install
|
20
|
+
|
21
|
+
## Configuration
|
22
|
+
|
23
|
+
You can obtain your API credentials from the [Infopark Console](https://console.infopark.net/).
|
24
|
+
|
25
|
+
```ruby
|
26
|
+
require 'infopark_webcrm_sdk'
|
27
|
+
|
28
|
+
Crm.configure do |config|
|
29
|
+
config.tenant = 'my_tenant'
|
30
|
+
config.login = 'my_login'
|
31
|
+
config.api_key = 'my_api_key'
|
32
|
+
end
|
33
|
+
```
|
34
|
+
|
35
|
+
## Example Usage
|
36
|
+
|
37
|
+
The Infopark WebCRM SDK provides the following Infopark WebCRM resources to your Ruby application:
|
38
|
+
|
39
|
+
* {Crm::Account}
|
40
|
+
* {Crm::Activity}
|
41
|
+
* {Crm::Collection}
|
42
|
+
* {Crm::Contact}
|
43
|
+
* {Crm::EventContact}
|
44
|
+
* {Crm::Event}
|
45
|
+
* {Crm::Mailing}
|
46
|
+
* {Crm::TemplateSet}
|
47
|
+
* {Crm::Type}
|
48
|
+
|
49
|
+
Most of these classes have methods such as {Crm::Core::Mixins::Findable::ClassMethods#find find}, {Crm::Core::Mixins::Modifiable::ClassMethods#create create}, {Crm::Core::Mixins::Modifiable#update update}, {Crm::Core::Mixins::Searchable::ClassMethods#query query}, and {Crm::Core::Mixins::Searchable::ClassMethods#where where}.
|
50
|
+
|
51
|
+
### Creating a Contact
|
52
|
+
|
53
|
+
```ruby
|
54
|
+
contact = Crm::Contact.create({
|
55
|
+
first_name: 'John',
|
56
|
+
last_name: 'Smith',
|
57
|
+
language: 'en',
|
58
|
+
locality: 'New York',
|
59
|
+
})
|
60
|
+
# => Crm::Contact
|
61
|
+
|
62
|
+
contact.first_name
|
63
|
+
# => 'John'
|
64
|
+
|
65
|
+
contact.id
|
66
|
+
# => 'e70a7123f499c5e0e9972ab4dbfb8fe3'
|
67
|
+
```
|
68
|
+
|
69
|
+
### Fetching and Updating a Contact
|
70
|
+
|
71
|
+
```ruby
|
72
|
+
# Retrieve the contact by ID
|
73
|
+
contact = Crm::Contact.find('e70a7123f499c5e0e9972ab4dbfb8fe3')
|
74
|
+
# => Crm::Contact
|
75
|
+
|
76
|
+
contact.last_name
|
77
|
+
# => 'Smith'
|
78
|
+
|
79
|
+
contact.locality
|
80
|
+
# => 'New York'
|
81
|
+
|
82
|
+
# Change this contact's locality
|
83
|
+
contact.update({locality: 'Boston'})
|
84
|
+
# => Crm::Contact
|
85
|
+
|
86
|
+
contact.last_name
|
87
|
+
# => 'Smith'
|
88
|
+
|
89
|
+
contact.locality
|
90
|
+
# => 'Boston'
|
91
|
+
```
|
92
|
+
|
93
|
+
### Searching for Contacts
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Crm::Contact.where(:login, :is_term, 'root').first
|
97
|
+
# => Crm::Contact
|
98
|
+
|
99
|
+
Crm::Contact.where(:locality, :is_term, 'Boston').
|
100
|
+
and(:last_name, :is_prefix, 'S').
|
101
|
+
sort_by(:last_name).
|
102
|
+
sort_order(:desc).
|
103
|
+
limit(2).
|
104
|
+
map(&:last_name)
|
105
|
+
# => ['Smith', 'Simpson']
|
106
|
+
```
|
107
|
+
|
108
|
+
## License
|
109
|
+
|
110
|
+
Copyright (c) 2015 [Infopark AG](https://infopark.com).
|
111
|
+
|
112
|
+
This software can be used and modified in accordance with the GNU Lesser General Public License
|
113
|
+
(LGPL-3.0). Please refer to LICENSE for details.
|
data/UPGRADE.md
ADDED
@@ -0,0 +1,507 @@
|
|
1
|
+
# Upgrade Guide
|
2
|
+
|
3
|
+
This guide assists you in upgrading from the **Infopark WebCRM Connector** (which uses API 1) to **Infopark WebCRM SDK** (which uses API 2).
|
4
|
+
|
5
|
+
You can upgrade incrementally to the Infopark WebCRM SDK.
|
6
|
+
This means that you don't need to upgrade your whole project at once.
|
7
|
+
Instead, include both the Infopark WebCRM Connector and the Infopark WebCRM SDK in your project and replace the code use case by use case.
|
8
|
+
Finally, remove the Infopark WebCRM Connector from the project.
|
9
|
+
|
10
|
+
To begin with, put both gems into the `Gemfile` of your project:
|
11
|
+
|
12
|
+
```ruby
|
13
|
+
gem "infopark_crm_connector"
|
14
|
+
gem "infopark_webcrm_sdk"
|
15
|
+
```
|
16
|
+
|
17
|
+
## Configuring the Infopark WebCRM SDK
|
18
|
+
|
19
|
+
Then, configure the Infopark WebCRM SDK to use your personal credentials when connecting to the Infopark WebCRM REST API.
|
20
|
+
You probably have a `webcrm.rb` or `crm_connector.rb` initializer file in your project which already contains the Infopark WebCRM Connector configuration.
|
21
|
+
Add the following lines to this file.
|
22
|
+
|
23
|
+
```ruby
|
24
|
+
require 'infopark_webcrm_sdk'
|
25
|
+
|
26
|
+
Crm.configure do |config|
|
27
|
+
config.tenant = ENV["CRM_TENANT"]
|
28
|
+
config.login = ENV["CRM_LOGIN"]
|
29
|
+
config.api_key = ENV["CRM_API_KEY"]
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Instead of reading the configuration values from the `ENV` you may also want to read them from a configuration file.
|
34
|
+
|
35
|
+
## General remarks
|
36
|
+
|
37
|
+
### The Crm namespace
|
38
|
+
|
39
|
+
All Infopark WebCRM SDK classes live under the `Crm` namespace whereas Infopark WebCRM Connector classes live under the `Infopark::Crm` namespace.
|
40
|
+
|
41
|
+
```ruby
|
42
|
+
# old:
|
43
|
+
Infopark::Crm::Contact.find(contact_id)
|
44
|
+
# new:
|
45
|
+
Crm::Contact.find(contact_id)
|
46
|
+
```
|
47
|
+
|
48
|
+
In case the resource could not be found, a `Crm::Errors::ResourceNotFound` error is raised.
|
49
|
+
Infopark WebCRM SDK will never raise an `ActiveResource::ResourceNotFound` error.
|
50
|
+
More on errors in the next section.
|
51
|
+
|
52
|
+
### Errors tell exactly what went wrong
|
53
|
+
|
54
|
+
For example, when trying to fetch a resource that could not be found, the `Crm::Errors::ResourceNotFound` error has a `missing_ids` property telling you the list of IDs that could not be found.
|
55
|
+
|
56
|
+
```ruby
|
57
|
+
begin
|
58
|
+
Crm::Contact.find("foo")
|
59
|
+
rescue Crm::Errors::ResourceNotFound => e
|
60
|
+
e.message # => "Items could not be found. Missing IDs: foo"
|
61
|
+
e.missing_ids # => ["foo"]
|
62
|
+
end
|
63
|
+
```
|
64
|
+
|
65
|
+
Or, when the Infopark WebCRM backend refuses to save a resource due to unsatisfied validation rules, the error contains the details.
|
66
|
+
|
67
|
+
```ruby
|
68
|
+
begin
|
69
|
+
Crm::Contact.create({
|
70
|
+
first_name: "John",
|
71
|
+
gender: "i don't know",
|
72
|
+
})
|
73
|
+
rescue Crm::Errors::InvalidValues => e
|
74
|
+
e.message # => "Validate the parameters and try again. gender is not included in the list: N, M, F, language is not included in the list, and last_name can't be blank."
|
75
|
+
e.validation_errors
|
76
|
+
# => [
|
77
|
+
# {
|
78
|
+
# "attribute" => "gender",
|
79
|
+
# "code" => "inclusion",
|
80
|
+
# "message" => "gender is not included in the list: N, M, F"
|
81
|
+
# },
|
82
|
+
# {
|
83
|
+
# "attribute" => "language",
|
84
|
+
# "code" => "inclusion",
|
85
|
+
# "message" => "language is not included in the list"
|
86
|
+
# },
|
87
|
+
# {
|
88
|
+
# "attribute" => "last_name",
|
89
|
+
# "code" => "blank",
|
90
|
+
# "message" => "last_name can't be blank"
|
91
|
+
# }
|
92
|
+
# ]
|
93
|
+
end
|
94
|
+
```
|
95
|
+
|
96
|
+
Validation errors contain the names of the attributes whose values are invalid, symbolic codes that you can use to look up custom translations of the error messages and English messages for convenience.
|
97
|
+
The symbolic codes are the Rails validation error codes where possible, e.g. `blank` and `inclusion`.
|
98
|
+
Infopark WebCRM adds its own codes such as `invalid_comment_contact_id` and `liquid_syntax_error`.
|
99
|
+
|
100
|
+
Furthermore, when updating a resource, Infopark WebCRM complains about attributes not defined in the resource type.
|
101
|
+
|
102
|
+
```ruby
|
103
|
+
begin
|
104
|
+
Crm::Contact.create({
|
105
|
+
foo: "bar",
|
106
|
+
})
|
107
|
+
rescue Crm::Errors::InvalidKeys => e
|
108
|
+
e.message # => "Unknown keys specified. foo is unknown."
|
109
|
+
e.validation_errors
|
110
|
+
# => [
|
111
|
+
# {
|
112
|
+
# "attribute" => "foo",
|
113
|
+
# "code" => "unknown",
|
114
|
+
# "message" => "foo is unknown"
|
115
|
+
# }
|
116
|
+
# ]
|
117
|
+
end
|
118
|
+
```
|
119
|
+
|
120
|
+
However, trying to set an internal read-only attribute such as `created_at` is ignored.
|
121
|
+
|
122
|
+
A list of errors and their properties can be found in the Infopark WebCRM SDK YARD docs.
|
123
|
+
|
124
|
+
### Write form models including their custom logic for every use case
|
125
|
+
|
126
|
+
One big change in the Infopark WebCRM SDK is that model classes are no longer based on `ActiveResource`.
|
127
|
+
They are much simpler now, and they don't behave like `ActiveModel` objects any more.
|
128
|
+
Instead of modifying a resource locally and then asking it to `save` itself, the Infopark WebCRM SDK requires the resource to be changed by passing the new attribute values to the `update` method.
|
129
|
+
Analogously, for creating a new resource, pass all of its attributes to `create`.
|
130
|
+
|
131
|
+
```ruby
|
132
|
+
contact = Crm::Contact.create({
|
133
|
+
first_name: "John",
|
134
|
+
last_name: "Smith",
|
135
|
+
language: "en",
|
136
|
+
locality: "New York",
|
137
|
+
gender: "M",
|
138
|
+
})
|
139
|
+
contact.locality # => "New York"
|
140
|
+
|
141
|
+
contact.update({
|
142
|
+
locality: "Hamburg",
|
143
|
+
language: "de",
|
144
|
+
})
|
145
|
+
contact.locality # => "Hamburg"
|
146
|
+
```
|
147
|
+
|
148
|
+
This means that you can no longer use them as form objects in your controllers and views.
|
149
|
+
You'd rather write a plain Ruby class for every use case, implement the `ActiveModel` interface and your custom logic in this class, and delegate to Infopark WebCRM SDK models for communicating with the Infopark WebCRM REST API.
|
150
|
+
For further details, see the API docs.
|
151
|
+
|
152
|
+
We recommend using the `active_attr` gem to simplify implementing the `ActiveModel` interface.
|
153
|
+
|
154
|
+
### Accessing attributes
|
155
|
+
|
156
|
+
You can access the attributes of an Infopark WebCRM SDK resource by means of method calls or the `[]` operator.
|
157
|
+
|
158
|
+
```ruby
|
159
|
+
contact = Crm::Contact.find(contact_id)
|
160
|
+
contact.last_name # => "Smith"
|
161
|
+
contact[:last_name] # => "Smith"
|
162
|
+
contact["last_name"] # => "Smith"
|
163
|
+
```
|
164
|
+
|
165
|
+
### Every attribute has a sane value
|
166
|
+
|
167
|
+
Attributes not set have a default value according to their attribute type.
|
168
|
+
Assuming that an Infopark WebCRM contact has no value for the `first_name` string attribute, reading it results in `""`, the empty string, not `nil`.
|
169
|
+
The same rule applies to numbers, boolean, arrays and hashes.
|
170
|
+
|
171
|
+
The only exception to this rule are date attributes whose values are in fact `nil` if they are not set.
|
172
|
+
If a date attribute has a value, it is automatically parsed and returned as a `Time` instance in the local timezone.
|
173
|
+
|
174
|
+
The consequence of this is that you don't need to write a lot of `nil` checks and no longer need to parse dates yourself.
|
175
|
+
|
176
|
+
### Renamed attributes
|
177
|
+
|
178
|
+
A couple of attributes were renamed in API 2.
|
179
|
+
You can access attributes using the Infopark WebCRM Connector and the old attribute name or the Infopark WebCRM SDK and the new attribute name.
|
180
|
+
|
181
|
+
The following attributes were renamed for all resources.
|
182
|
+
|
183
|
+
* `kind` => `type_id` (e.g. `"contact-form"`)
|
184
|
+
* `type` => `base_type` (e.g. `"Activity"`)
|
185
|
+
|
186
|
+
Further attribute name changes are documented below.
|
187
|
+
|
188
|
+
### Authentication
|
189
|
+
|
190
|
+
Infopark WebCRM SDK offers two methods for authenticating a contact.
|
191
|
+
|
192
|
+
1. `Crm::Contact.authenticate` returns the authenticated contact or `nil`.
|
193
|
+
2. `Crm::Contact.authenticate!` returns the authenticated contact or raises a `Crm::Errors::AuthenticationFailed` error.
|
194
|
+
|
195
|
+
### All resources have a changelog
|
196
|
+
|
197
|
+
The changes history known from the WebCRM GUI is now also available in the new API.
|
198
|
+
You can retrieve up to 100 changelog entries of any resource.
|
199
|
+
They are sorted in reverse chronological order.
|
200
|
+
|
201
|
+
```ruby
|
202
|
+
contact = Crm::Contact.find(contact_id)
|
203
|
+
contact.changes.each do |change|
|
204
|
+
change.changed_at # => 2014-11-26 15:37:27 +0100
|
205
|
+
change.changed_by # => "root"
|
206
|
+
change.details(limit: 1).each do |attr_name, detail|
|
207
|
+
attr_name # => "email"
|
208
|
+
detail.before # => "john.smith@example.org"
|
209
|
+
detail.after # => "johann.schmidt@example.org"
|
210
|
+
end
|
211
|
+
end
|
212
|
+
```
|
213
|
+
|
214
|
+
### All resources can be undeleted
|
215
|
+
|
216
|
+
Previously, there was no way to undelete a deleted resource by means of the API.
|
217
|
+
With the API 2, all resources have an `undelete` method.
|
218
|
+
|
219
|
+
```ruby
|
220
|
+
contact = Crm::Contact.find(contact_id)
|
221
|
+
contact.deleted? # => true
|
222
|
+
contact.undelete
|
223
|
+
contact.deleted? # => false
|
224
|
+
```
|
225
|
+
|
226
|
+
## The individual resources: changes & features
|
227
|
+
|
228
|
+
### Search
|
229
|
+
|
230
|
+
Infopark WebCRM comes with a global search.
|
231
|
+
All resource types are searched simultaneously.
|
232
|
+
The following example finds both accounts and contacts located in Rome.
|
233
|
+
Both accounts and contacts have a locality attribute.
|
234
|
+
|
235
|
+
```ruby
|
236
|
+
Crm.search(
|
237
|
+
filters: [
|
238
|
+
{field: 'locality', condition: 'equals', value: 'Rome'},
|
239
|
+
],
|
240
|
+
sort_by: 'updated_at'
|
241
|
+
)
|
242
|
+
```
|
243
|
+
|
244
|
+
In order to limit the search hits to contacts, add another filter.
|
245
|
+
|
246
|
+
```ruby
|
247
|
+
Crm.search(
|
248
|
+
filters: [
|
249
|
+
{field: 'locality', condition: 'equals', value: 'Rome'},
|
250
|
+
{field: 'base_type', condition: 'equals', value: 'Contact'},
|
251
|
+
],
|
252
|
+
sort_by: 'updated_at'
|
253
|
+
)
|
254
|
+
```
|
255
|
+
|
256
|
+
The power of the new search API comes into play when building more complex queries.
|
257
|
+
Based on this low-level `search` method, the SDK lets you compose search queries by means of method chaining.
|
258
|
+
Start with the `where` method, then append methods such as `and`, `limit`, and `sort_by` to further refine the search.
|
259
|
+
Finally, run the search by iterating over the results:
|
260
|
+
|
261
|
+
```ruby
|
262
|
+
Crm::Activity.
|
263
|
+
where("type_id", :equals, "support-case").
|
264
|
+
and("contact_id", :equals, contact_id).
|
265
|
+
and_not("state", :equals, "closed").
|
266
|
+
query("I have got a problem").
|
267
|
+
limit(10).
|
268
|
+
sort_by("updated_at").desc.
|
269
|
+
each do |activity|
|
270
|
+
puts activity.title
|
271
|
+
end
|
272
|
+
```
|
273
|
+
|
274
|
+
Further examples to illustrate the new search features:
|
275
|
+
|
276
|
+
```ruby
|
277
|
+
# old:
|
278
|
+
Infopark::Crm::Contact.search(params: {q: "something"}).take(10)
|
279
|
+
Infopark::Crm::Contact.search(params: {login: login}).first
|
280
|
+
# new:
|
281
|
+
Crm::Contact.query("something").limit(10).to_a
|
282
|
+
Crm::Contact.where(:login, :equals, login).limit(1).first
|
283
|
+
```
|
284
|
+
|
285
|
+
### Accounts
|
286
|
+
|
287
|
+
The `merge_and_delete` method merges two accounts and deletes the one for which the method was called.
|
288
|
+
This feature is already known from the WebCRM GUI.
|
289
|
+
All items associated with the account to be deleted, e.g. activities, are transfered to the target account.
|
290
|
+
|
291
|
+
```ruby
|
292
|
+
account_to_delete = Crm::Account.find(account_id)
|
293
|
+
account_to_delete.merge_and_delete(target_account_id)
|
294
|
+
account_to_delete.deleted? # => true
|
295
|
+
```
|
296
|
+
|
297
|
+
### Activities
|
298
|
+
|
299
|
+
When associating an attachment with an activity comment, you can pass an open file instead of an attachment ID.
|
300
|
+
In this case, the Infopark WebCRM SDK automatically uploads the file content using the attachments API.
|
301
|
+
It then references this attachment ID in the `comment_attachments` field.
|
302
|
+
|
303
|
+
```ruby
|
304
|
+
activity = Crm::Activity.create({
|
305
|
+
type_id: 'support-case',
|
306
|
+
state: 'created',
|
307
|
+
title: 'I have a question',
|
308
|
+
comment_notes: 'Please see the attached screenshot.',
|
309
|
+
comment_attachments: [File.new('screenshot.jpg')],
|
310
|
+
})
|
311
|
+
activity.comments.last.attachments.first.download_url
|
312
|
+
# => "https://.../screenshot.jpg"
|
313
|
+
```
|
314
|
+
|
315
|
+
The following activity attributes were renamed in API 2:
|
316
|
+
|
317
|
+
* `appointment_dtend_at` => `dtend_at`
|
318
|
+
* `appointment_dtstart_at` => `dtstart_at`
|
319
|
+
* `appointment_location` => `location`
|
320
|
+
* `contact_id` => `contact_ids`
|
321
|
+
|
322
|
+
### AttachmentStore
|
323
|
+
|
324
|
+
Actions related to attachments were streamlined.
|
325
|
+
The Ruby class responsible for attachments is now `AttachmentStore`.
|
326
|
+
The main class methods of the attachment store are `generate_upload_permission` and `generate_download_url`.
|
327
|
+
|
328
|
+
When uploading attachments using Ruby, we recommend utilizing the implicit uploading facility of activity comments as a shortcut.
|
329
|
+
|
330
|
+
### Collections
|
331
|
+
|
332
|
+
The `Collection` API is new.
|
333
|
+
An Infopark WebCRM collection is a saved search.
|
334
|
+
The search filters as well as the search results are part of the collection.
|
335
|
+
|
336
|
+
```ruby
|
337
|
+
collection = Crm::Collection.create({
|
338
|
+
title: 'My Collection',
|
339
|
+
collection_type: 'contact',
|
340
|
+
filters: [
|
341
|
+
[
|
342
|
+
{field: 'contact.last_name', condition: 'equals', value: 'Smith'}
|
343
|
+
]
|
344
|
+
]
|
345
|
+
})
|
346
|
+
```
|
347
|
+
|
348
|
+
To execute such a saved search, call `compute`.
|
349
|
+
|
350
|
+
```ruby
|
351
|
+
collection.compute
|
352
|
+
```
|
353
|
+
|
354
|
+
The results are persisted and can be accessed via `output_items`.
|
355
|
+
|
356
|
+
```ruby
|
357
|
+
collection.output_items.each do |contact|
|
358
|
+
contact.last_name # => "Smith"
|
359
|
+
end
|
360
|
+
```
|
361
|
+
|
362
|
+
For details, see the Infopark WebCRM SDK docs.
|
363
|
+
|
364
|
+
### Contacts
|
365
|
+
|
366
|
+
`Contact#merge_and_delete` works analogously to `Account#merge_and_delete`.
|
367
|
+
Refer to the "Accounts" section for details.
|
368
|
+
|
369
|
+
The following contact attributes were renamed in API 2:
|
370
|
+
|
371
|
+
* `password_request_at` => `password_requested_at`
|
372
|
+
|
373
|
+
### EventContacts
|
374
|
+
|
375
|
+
With the exception of the renamed common attributes (see above), nothing has changed.
|
376
|
+
|
377
|
+
### Events
|
378
|
+
|
379
|
+
The following event attributes were renamed in API 2:
|
380
|
+
|
381
|
+
* `custom_attributes` (array) => `attribute_definitions` (hash) + `attribute_order` (array)
|
382
|
+
|
383
|
+
### Mailings
|
384
|
+
|
385
|
+
You can render the plain-text and HTML templates of a mailing as they would look for a given contact ID by means of `Mailing#render_preview`.
|
386
|
+
|
387
|
+
```ruby
|
388
|
+
mailing = Crm::Mailing.create({
|
389
|
+
email_from: "Marketing <marketing@example.com>",
|
390
|
+
email_reply_to: "marketing-replyto@example.com",
|
391
|
+
email_subject: "Invitation to our exhibition",
|
392
|
+
html_body: '<h1>Welcome {{contact.first_name}} {{contact.last_name}}</h1>',
|
393
|
+
text_body: 'Welcome {{contact.first_name}} {{contact.last_name}}',
|
394
|
+
title: 'Our Annual Exhibition',
|
395
|
+
type_id: 'newsletter',
|
396
|
+
})
|
397
|
+
mailing.render_preview(contact_id)
|
398
|
+
# => {
|
399
|
+
# "email_from" => "Marketing <marketing@example.com>",
|
400
|
+
# "email_reply_to" => "marketing-replyto@example.com",
|
401
|
+
# "email_subject" => "Invitation to our exhibition",
|
402
|
+
# "email_to" => "john.smith@example.org",
|
403
|
+
# "html_body" => "<h1>Welcome John Smith</h1>",
|
404
|
+
# "text_body" => "Welcome John Smith",
|
405
|
+
# }
|
406
|
+
```
|
407
|
+
|
408
|
+
`Mailing#send_single_email` sends an e-mail to an individual contact after the mailing has already been released.
|
409
|
+
|
410
|
+
`Mailing#send_me_a_proof_email` sends an e-mail to the authenticated API user, i.e. to the user you configured in the `Crm.configure` block.
|
411
|
+
|
412
|
+
`Mailing#release` releases a mailing and sends e-mails to all recipients.
|
413
|
+
|
414
|
+
```ruby
|
415
|
+
recipients = Crm::Collection.create({
|
416
|
+
title: 'Newsletter Recipients',
|
417
|
+
collection_type: 'contact',
|
418
|
+
filters: [
|
419
|
+
[
|
420
|
+
{field: 'contact.locality', condition: 'equals', value: "Berlin"},
|
421
|
+
]
|
422
|
+
]
|
423
|
+
})
|
424
|
+
recipients.compute
|
425
|
+
|
426
|
+
newsletter_mailing = Crm::Mailing.create({
|
427
|
+
title: 'Newsletter',
|
428
|
+
type_id: 'newsletter',
|
429
|
+
collection_id: recipients.id,
|
430
|
+
email_from: "Marketing <marketing@example.com>",
|
431
|
+
})
|
432
|
+
newsletter_mailing.release
|
433
|
+
```
|
434
|
+
|
435
|
+
The following mailing attributes were renamed in API 2:
|
436
|
+
|
437
|
+
* `contact_collection_id` => `collection_id`
|
438
|
+
* `dtstart_at` => `planned_release_at`
|
439
|
+
* `body` => `text_body`
|
440
|
+
|
441
|
+
|
442
|
+
### TemplateSet
|
443
|
+
|
444
|
+
Templates can no longer be accessed using the `Infopark::Crm::System.templates` hash.
|
445
|
+
Instead, they are now a normal attribute, `templates`, of the `Crm::TemplateSet.singleton` resource.
|
446
|
+
|
447
|
+
```ruby
|
448
|
+
ts = Crm::TemplateSet.singleton
|
449
|
+
ts.templates['password_request_email_from'] # => "bounces@example.com"
|
450
|
+
ts.updated_at # => 2015-02-16 11:19:28 +0100
|
451
|
+
ts.updated_by # => "root"
|
452
|
+
```
|
453
|
+
|
454
|
+
Compared to the Infopark WebCRM Connector, setting a subset of templates is sufficient.
|
455
|
+
Templates that are not specified are no longer deleted.
|
456
|
+
Set templates explicitly to `nil` to remove them from the template set.
|
457
|
+
|
458
|
+
```ruby
|
459
|
+
ts = Crm::TemplateSet.singleton
|
460
|
+
ts.update(templates: {
|
461
|
+
'password_request_email_from' => nil,
|
462
|
+
'foo' => 'bar',
|
463
|
+
})
|
464
|
+
ts.templates['password_request_email_from'] # => nil
|
465
|
+
ts.templates['foo'] # => "bar"
|
466
|
+
```
|
467
|
+
|
468
|
+
### Types
|
469
|
+
|
470
|
+
Types were formerly known as custom types.
|
471
|
+
|
472
|
+
`Crm::Type.all` retrieves a list of all types, i.e. custom types and built-in types.
|
473
|
+
|
474
|
+
Every type has an `id`, e.g. `contact` or `support-case`, which is referenced as `type_id` by instances of these classes.
|
475
|
+
|
476
|
+
`Crm::Type.find` loads the type by its ID.
|
477
|
+
|
478
|
+
```ruby
|
479
|
+
contact = Crm::Contact.find(contact_id)
|
480
|
+
contact.type_id # => "contact"
|
481
|
+
|
482
|
+
contact_type = Crm::Type.find("contact")
|
483
|
+
contact_type.base_type # => "Type"
|
484
|
+
contact_type.id # => "contact"
|
485
|
+
contact_type.item_base_type # => "Contact"
|
486
|
+
contact_type.attribute_definitions
|
487
|
+
# => {
|
488
|
+
# "custom_my_foo" => {
|
489
|
+
# "title" => "my foo attribute",
|
490
|
+
# "mandatory" => false,
|
491
|
+
# "max_length" => 80,
|
492
|
+
# "attribute_type" => "string",
|
493
|
+
# "create" => true,
|
494
|
+
# "update" => true,
|
495
|
+
# "read" => true,
|
496
|
+
# }
|
497
|
+
# }
|
498
|
+
|
499
|
+
support_case = Crm::Activity.find(support_case_id)
|
500
|
+
support_case.type_id # => "support-case"
|
501
|
+
|
502
|
+
support_case_type = Crm::Type.find('support-case')
|
503
|
+
support_case_type.base_type # => "Type"
|
504
|
+
support_case_type.id # => "support-case"
|
505
|
+
support_case_type.item_base_type # => "Activity"
|
506
|
+
support_case_type.attribute_definitions # => {}
|
507
|
+
```
|