client_success 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +11 -0
- data/.rspec +3 -0
- data/.rubocop.yml +466 -0
- data/.travis.yml +7 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +111 -0
- data/README.md +52 -0
- data/Rakefile +6 -0
- data/bin/console +14 -0
- data/bin/setup +8 -0
- data/client_success.gemspec +44 -0
- data/lib/client_success/access_token.rb +25 -0
- data/lib/client_success/client.rb +115 -0
- data/lib/client_success/client_type.rb +18 -0
- data/lib/client_success/connection.rb +99 -0
- data/lib/client_success/contact.rb +104 -0
- data/lib/client_success/domain_model/access_token.rb +11 -0
- data/lib/client_success/domain_model/client.rb +14 -0
- data/lib/client_success/domain_model/client_type.rb +14 -0
- data/lib/client_success/domain_model/contact.rb +14 -0
- data/lib/client_success/domain_model/custom_field_value.rb +9 -0
- data/lib/client_success/domain_model/employee.rb +14 -0
- data/lib/client_success/domain_model/product.rb +10 -0
- data/lib/client_success/domain_model/security_role.rb +9 -0
- data/lib/client_success/domain_model/status.rb +9 -0
- data/lib/client_success/domain_model/subscription.rb +12 -0
- data/lib/client_success/domain_model/success_cycle.rb +9 -0
- data/lib/client_success/domain_model/to_do.rb +9 -0
- data/lib/client_success/employee.rb +18 -0
- data/lib/client_success/product.rb +16 -0
- data/lib/client_success/schema/client/create.rb +34 -0
- data/lib/client_success/schema/client/update.rb +37 -0
- data/lib/client_success/schema/contact/create.rb +28 -0
- data/lib/client_success/schema/contact/update.rb +27 -0
- data/lib/client_success/schema/subscription/create.rb +20 -0
- data/lib/client_success/schema/subscription/update.rb +21 -0
- data/lib/client_success/status.rb +23 -0
- data/lib/client_success/subscription.rb +51 -0
- data/lib/client_success/to_do.rb +23 -0
- data/lib/client_success/types.rb +7 -0
- data/lib/client_success/version.rb +3 -0
- data/lib/client_success.rb +18 -0
- metadata +266 -0
@@ -0,0 +1,44 @@
|
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
+
require "client_success/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |spec|
|
6
|
+
spec.name = "client_success"
|
7
|
+
spec.version = ClientSuccess::VERSION
|
8
|
+
spec.authors = ["Practice Ignition"]
|
9
|
+
spec.email = ["dev@practiceignition.com"]
|
10
|
+
|
11
|
+
spec.summary = "An unofficial Ruby wrapper for Client Success's REST API"
|
12
|
+
spec.homepage = "https://github.com/ignitionapp/"
|
13
|
+
|
14
|
+
# Specify which files should be added to the gem when it is released.
|
15
|
+
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
16
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
17
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
18
|
+
end
|
19
|
+
spec.bindir = "exe"
|
20
|
+
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
21
|
+
spec.require_paths = ["lib"]
|
22
|
+
|
23
|
+
spec.add_development_dependency("bundler", "~> 2.0")
|
24
|
+
spec.add_development_dependency("rake", ">= 12.3.3")
|
25
|
+
spec.add_development_dependency("rspec", "~> 3.0")
|
26
|
+
|
27
|
+
spec.add_development_dependency("vcr")
|
28
|
+
spec.add_development_dependency("faker")
|
29
|
+
|
30
|
+
spec.add_development_dependency("rubocop", "0.77.0")
|
31
|
+
spec.add_development_dependency("rubocop-rspec")
|
32
|
+
|
33
|
+
spec.add_runtime_dependency("faraday")
|
34
|
+
spec.add_runtime_dependency("faraday_middleware")
|
35
|
+
|
36
|
+
# TODO: don't force the use of typhoeus
|
37
|
+
spec.add_runtime_dependency("typhoeus")
|
38
|
+
|
39
|
+
spec.add_runtime_dependency("dry-types", "0.11.0")
|
40
|
+
spec.add_runtime_dependency("hashie")
|
41
|
+
|
42
|
+
# TODO: remove activesupport as a dependency
|
43
|
+
spec.add_runtime_dependency("activesupport", "~> 5.2")
|
44
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_relative "connection"
|
2
|
+
require_relative "domain_model/access_token"
|
3
|
+
|
4
|
+
module ClientSuccess
|
5
|
+
module AccessToken
|
6
|
+
extend self
|
7
|
+
|
8
|
+
class Error < StandardError; end
|
9
|
+
class InvalidCredentials < Error; end
|
10
|
+
|
11
|
+
def create(username:, password:,
|
12
|
+
connection: ClientSuccess::Connection.new)
|
13
|
+
response = connection.post("/v1/auth",
|
14
|
+
username: username,
|
15
|
+
password: password)
|
16
|
+
|
17
|
+
payload = response.body
|
18
|
+
|
19
|
+
DomainModel::AccessToken.new(
|
20
|
+
payload.deep_transform_keys(&:underscore))
|
21
|
+
rescue Connection::Unauthorised
|
22
|
+
raise InvalidCredentials, "invalid username or password"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require_relative "connection"
|
2
|
+
require_relative "domain_model/client"
|
3
|
+
require_relative "schema/client/create"
|
4
|
+
require_relative "schema/client/update"
|
5
|
+
|
6
|
+
module ClientSuccess
|
7
|
+
module Client
|
8
|
+
extend self
|
9
|
+
|
10
|
+
class Error < StandardError; end
|
11
|
+
class NotFound < Error; end
|
12
|
+
|
13
|
+
def list_all(assigned_csm_id: nil, active_only: true,
|
14
|
+
connection:)
|
15
|
+
params = {
|
16
|
+
"assignedCsmId" => assigned_csm_id,
|
17
|
+
"activeOnly" => active_only
|
18
|
+
}
|
19
|
+
|
20
|
+
response = connection.get(
|
21
|
+
"/v1/clients?#{params.compact.to_query}")
|
22
|
+
|
23
|
+
response.body.map do |payload|
|
24
|
+
DomainModel::Client.new(
|
25
|
+
payload.deep_transform_keys(&:underscore))
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def get_details(client_id:, connection:)
|
30
|
+
response = connection.get(
|
31
|
+
"/v1/clients/#{client_id}")
|
32
|
+
|
33
|
+
payload = response.body
|
34
|
+
|
35
|
+
DomainModel::Client.new(
|
36
|
+
payload.deep_transform_keys(&:underscore))
|
37
|
+
rescue Connection::NotFound
|
38
|
+
raise NotFound, "client with id '#{client_id}' not found"
|
39
|
+
end
|
40
|
+
|
41
|
+
def get_details_by_external_id(external_id:, connection:)
|
42
|
+
params = {
|
43
|
+
"externalId" => external_id
|
44
|
+
}
|
45
|
+
|
46
|
+
response = connection.get(
|
47
|
+
"/v1/clients?#{params.compact.to_query}")
|
48
|
+
|
49
|
+
payload = response.body
|
50
|
+
|
51
|
+
DomainModel::Client.new(
|
52
|
+
payload.deep_transform_keys(&:underscore))
|
53
|
+
rescue Connection::NotFound
|
54
|
+
raise NotFound, "client with external id '#{external_id}' not found"
|
55
|
+
end
|
56
|
+
|
57
|
+
def create(attributes:, connection:)
|
58
|
+
body = Schema::Client::Create[attributes]
|
59
|
+
.transform_keys { |k| k.to_s.camelize(:lower) }
|
60
|
+
.to_json
|
61
|
+
|
62
|
+
response = connection.post(
|
63
|
+
"/v1/clients", body)
|
64
|
+
|
65
|
+
payload = response.body
|
66
|
+
|
67
|
+
# TODO: find a better way to deal with api weirdness here
|
68
|
+
payload["customFieldValues"].compact!
|
69
|
+
|
70
|
+
DomainModel::Client.new(
|
71
|
+
payload.deep_transform_keys(&:underscore))
|
72
|
+
end
|
73
|
+
|
74
|
+
# NOTE: according to the api documentation, this is _not_ a PATCH operation,
|
75
|
+
# i.e. any fields not supplied will be set to null - so make sure you
|
76
|
+
# supply everything :)
|
77
|
+
def update(client_id:, attributes:, connection:)
|
78
|
+
body = attributes
|
79
|
+
.deep_transform_keys { |k| k.to_s.camelize(:lower) }
|
80
|
+
.to_json
|
81
|
+
|
82
|
+
response = connection.put(
|
83
|
+
"/v1/clients/#{client_id}", body)
|
84
|
+
|
85
|
+
payload = response.body
|
86
|
+
|
87
|
+
# TODO: find a better way to deal with api weirdness here
|
88
|
+
payload["customFieldValues"].compact!
|
89
|
+
|
90
|
+
DomainModel::Client.new(
|
91
|
+
payload.deep_transform_keys(&:underscore))
|
92
|
+
end
|
93
|
+
|
94
|
+
def update_custom_field(client_id:, custom_field_name:, value:, connection:)
|
95
|
+
body = {
|
96
|
+
custom_field_name => value.to_s
|
97
|
+
}
|
98
|
+
|
99
|
+
begin
|
100
|
+
connection.patch(
|
101
|
+
"/v1/customfield/value/client/#{client_id}", body)
|
102
|
+
rescue Connection::ParsingError => error
|
103
|
+
# NOTE: request submitted to resolve invalid JSON response from client
|
104
|
+
# success for this endpoint
|
105
|
+
raise error unless error.message =~ /Update successful/
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def delete(client_id:, connection:)
|
110
|
+
# TODO: handle response
|
111
|
+
connection.delete(
|
112
|
+
"/v1/clients/#{client_id}")
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "connection"
|
2
|
+
require_relative "domain_model/client_type"
|
3
|
+
|
4
|
+
module ClientSuccess
|
5
|
+
module ClientType
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def list_all(connection:)
|
9
|
+
response = connection.get(
|
10
|
+
"/v1/client-segments")
|
11
|
+
|
12
|
+
response.body.map do |payload|
|
13
|
+
DomainModel::ClientType.new(
|
14
|
+
payload.deep_transform_keys(&:underscore))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require "faraday"
|
2
|
+
require "faraday_middleware"
|
3
|
+
|
4
|
+
module ClientSuccess
|
5
|
+
class Connection
|
6
|
+
class Error < StandardError; end
|
7
|
+
|
8
|
+
class BadRequest < Error; end
|
9
|
+
class Unauthorised < Error; end
|
10
|
+
class NotFound < Error; end
|
11
|
+
|
12
|
+
class ParsingError < Error; end
|
13
|
+
|
14
|
+
class << self
|
15
|
+
def authorised(access_token)
|
16
|
+
new.tap { |conn| conn.access_token = access_token }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def logger
|
21
|
+
# TODO: something better than this
|
22
|
+
Logger.new(STDOUT).tap do |l|
|
23
|
+
l.level = Logger::WARN
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def access_token
|
28
|
+
headers["Authorization"]
|
29
|
+
end
|
30
|
+
|
31
|
+
def access_token=(access_token)
|
32
|
+
headers["Authorization"] = access_token
|
33
|
+
end
|
34
|
+
|
35
|
+
def get(path, headers = {}, &block)
|
36
|
+
request { adapter.get(path, headers, &block) }
|
37
|
+
end
|
38
|
+
|
39
|
+
def head(path, headers = {}, &block)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def post(path, body = nil, headers = {}, &block)
|
44
|
+
request { adapter.post(path, body, headers, &block) }
|
45
|
+
end
|
46
|
+
|
47
|
+
def put(path, body = nil, headers = {}, &block)
|
48
|
+
request { adapter.put(path, body, headers, &block) }
|
49
|
+
end
|
50
|
+
|
51
|
+
def patch(path, body = nil, headers = {}, &block)
|
52
|
+
request { adapter.patch(path, body, headers, &block) }
|
53
|
+
end
|
54
|
+
|
55
|
+
def delete(path, headers = {}, &block)
|
56
|
+
request { adapter.delete(path, headers, &block) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def options(path, headers = {}, &block)
|
60
|
+
raise NotImplementedError
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def headers
|
66
|
+
adapter.headers
|
67
|
+
end
|
68
|
+
|
69
|
+
def adapter
|
70
|
+
@adapter ||= Faraday.new(url: "https://api.clientsuccess.com") do |faraday|
|
71
|
+
faraday.request(:json)
|
72
|
+
faraday.response(:json, content_type: /\bjson$/)
|
73
|
+
faraday.response(:logger, logger)
|
74
|
+
faraday.use(Faraday::Response::RaiseError)
|
75
|
+
faraday.adapter(Faraday.default_adapter)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def request
|
80
|
+
yield
|
81
|
+
rescue Faraday::ParsingError => error
|
82
|
+
raise ParsingError, error
|
83
|
+
rescue Faraday::ClientError => error
|
84
|
+
case error.response[:status]
|
85
|
+
when 400
|
86
|
+
# TODO: parse out userMessage from the response here
|
87
|
+
raise BadRequest, error
|
88
|
+
when 401
|
89
|
+
raise Unauthorised, error
|
90
|
+
when 404
|
91
|
+
raise NotFound, error
|
92
|
+
else
|
93
|
+
raise Error, error
|
94
|
+
end
|
95
|
+
rescue SignalException => error
|
96
|
+
raise Error, error
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require_relative "domain_model/contact"
|
2
|
+
require_relative "schema/contact/create"
|
3
|
+
require_relative "schema/contact/update"
|
4
|
+
|
5
|
+
module ClientSuccess
|
6
|
+
module Contact
|
7
|
+
extend self
|
8
|
+
|
9
|
+
class Error < StandardError; end
|
10
|
+
class NotFound < Error; end
|
11
|
+
|
12
|
+
def list_all(client_id:, connection:)
|
13
|
+
response = connection.get(
|
14
|
+
"/v1/clients/#{client_id}/contacts")
|
15
|
+
|
16
|
+
response.body.map do |payload|
|
17
|
+
DomainModel::Contact.new(
|
18
|
+
payload.deep_transform_keys(&:underscore))
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def get_summary(client_id:, contact_id:, connection:)
|
23
|
+
response = connection.get(
|
24
|
+
"/v1/clients/#{client_id}/contacts/#{contact_id}")
|
25
|
+
|
26
|
+
payload = response.body
|
27
|
+
|
28
|
+
DomainModel::Contact.new(
|
29
|
+
payload.deep_transform_keys(&:underscore))
|
30
|
+
end
|
31
|
+
|
32
|
+
def get_details(client_id:, contact_id:, connection:)
|
33
|
+
response = connection.get(
|
34
|
+
"/v1/clients/#{client_id}/contacts/#{contact_id}/details")
|
35
|
+
|
36
|
+
payload = response.body
|
37
|
+
|
38
|
+
DomainModel::Contact.new(
|
39
|
+
payload.deep_transform_keys(&:underscore))
|
40
|
+
end
|
41
|
+
|
42
|
+
def create(client_id:, attributes:, connection:)
|
43
|
+
body = Schema::Contact::Create[attributes]
|
44
|
+
.transform_keys { |k| k.to_s.camelize(:lower) }
|
45
|
+
.to_json
|
46
|
+
|
47
|
+
response = connection.post(
|
48
|
+
"/v1/clients/#{client_id}/contacts", body)
|
49
|
+
|
50
|
+
payload = response.body
|
51
|
+
|
52
|
+
DomainModel::Contact.new(
|
53
|
+
payload.deep_transform_keys(&:underscore))
|
54
|
+
end
|
55
|
+
|
56
|
+
def update(id:, client_id:, attributes:, connection:)
|
57
|
+
body = Schema::Contact::Update[attributes]
|
58
|
+
.transform_keys { |k| k.to_s.camelize(:lower) }
|
59
|
+
.to_json
|
60
|
+
|
61
|
+
response = connection.put("/v1/clients/#{client_id}/contacts/#{id}/details", body)
|
62
|
+
|
63
|
+
payload = response.body
|
64
|
+
|
65
|
+
DomainModel::Contact.new(
|
66
|
+
payload.deep_transform_keys(&:underscore))
|
67
|
+
end
|
68
|
+
|
69
|
+
def delete(id:, client_id:, connection:)
|
70
|
+
connection.delete("/v1/clients/#{client_id}/contacts/#{id}")
|
71
|
+
end
|
72
|
+
|
73
|
+
def search_by_email(email:, connection:)
|
74
|
+
search(term: email, connection: connection)
|
75
|
+
.reject { |contact| contact["email"].nil? }
|
76
|
+
.select { |contact| contact["email"].downcase == email.downcase }
|
77
|
+
end
|
78
|
+
|
79
|
+
def get_details_by_client_external_id_and_email(client_external_id:, email:, connection:)
|
80
|
+
params = {
|
81
|
+
"clientExternalId" => client_external_id,
|
82
|
+
"email" => email
|
83
|
+
}
|
84
|
+
|
85
|
+
response = connection.get(
|
86
|
+
"/v1/contacts?#{params.compact.to_query}")
|
87
|
+
|
88
|
+
# for some reason the ClientSuccess API does not return a 404
|
89
|
+
# but instead a body containing the string "null" if the contact is not found
|
90
|
+
# this is probably a security restriction on their end, but we will instead raise an error
|
91
|
+
|
92
|
+
if response.body.blank?
|
93
|
+
raise NotFound, "contact with email '#{email}' not found on client '#{client_external_id}'"
|
94
|
+
else
|
95
|
+
payload = response.body
|
96
|
+
DomainModel::Contact.new(payload.deep_transform_keys(&:underscore))
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def search(term:, connection:)
|
101
|
+
connection.get("/v1/contacts/search?term='#{term}'").body
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "custom_field_value"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module DomainModel
|
5
|
+
class Client < Hash
|
6
|
+
include Hashie::Extensions::MergeInitializer
|
7
|
+
include Hashie::Extensions::IndifferentAccess
|
8
|
+
include Hashie::Extensions::MethodAccess
|
9
|
+
include Hashie::Extensions::Coercion
|
10
|
+
|
11
|
+
coerce_key :custom_field_values, Array[CustomFieldValue]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "success_cycle"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module DomainModel
|
5
|
+
class ClientType < Hash
|
6
|
+
include Hashie::Extensions::MergeInitializer
|
7
|
+
include Hashie::Extensions::IndifferentAccess
|
8
|
+
include Hashie::Extensions::MethodAccess
|
9
|
+
include Hashie::Extensions::Coercion
|
10
|
+
|
11
|
+
coerce_key :success_cycles, Array[SuccessCycle]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
# require_relative "custom_field_value"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module DomainModel
|
5
|
+
class Contact < Hash
|
6
|
+
include Hashie::Extensions::MergeInitializer
|
7
|
+
include Hashie::Extensions::IndifferentAccess
|
8
|
+
include Hashie::Extensions::MethodAccess
|
9
|
+
# include Hashie::Extensions::Coercion
|
10
|
+
|
11
|
+
# coerce_key :custom_field_values, Array[CustomFieldValue]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require_relative "security_role"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module DomainModel
|
5
|
+
class Employee < Hash
|
6
|
+
include Hashie::Extensions::MergeInitializer
|
7
|
+
include Hashie::Extensions::IndifferentAccess
|
8
|
+
include Hashie::Extensions::MethodAccess
|
9
|
+
include Hashie::Extensions::Coercion
|
10
|
+
|
11
|
+
coerce_key :security_roles, Array[SecurityRole]
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require_relative "custom_field_value"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module DomainModel
|
5
|
+
class Subscription < Hash
|
6
|
+
include Hashie::Extensions::MergeInitializer
|
7
|
+
include Hashie::Extensions::IndifferentAccess
|
8
|
+
include Hashie::Extensions::MethodAccess
|
9
|
+
include Hashie::Extensions::Coercion
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,18 @@
|
|
1
|
+
require_relative "connection"
|
2
|
+
require_relative "domain_model/employee"
|
3
|
+
|
4
|
+
module ClientSuccess
|
5
|
+
module Employee
|
6
|
+
extend self
|
7
|
+
|
8
|
+
def list_all(connection:)
|
9
|
+
response = connection.get(
|
10
|
+
"/v1/employees")
|
11
|
+
|
12
|
+
response.body.map do |payload|
|
13
|
+
DomainModel::Employee.new(
|
14
|
+
payload.deep_transform_keys(&:underscore))
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_relative "domain_model/product"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module Product
|
5
|
+
extend self
|
6
|
+
|
7
|
+
def list_all(connection:)
|
8
|
+
response = connection.get("/v1/products")
|
9
|
+
|
10
|
+
response.body.map do |payload|
|
11
|
+
DomainModel::Product.new(
|
12
|
+
payload.deep_transform_keys(&:underscore))
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
require_relative "../../types"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module Schema
|
5
|
+
module Client
|
6
|
+
# TODO: upgrade dry types to use latest schema functions
|
7
|
+
Create = Types::Hash.schema(
|
8
|
+
name: Types::Strict::String,
|
9
|
+
site_url: Types::Strict::String,
|
10
|
+
zip: Types::Strict::String,
|
11
|
+
status_id: Types::Coercible::Int,
|
12
|
+
inception_date: Types::Strict::String, # TODO
|
13
|
+
created_by_employee_id: Types::Coercible::Int,
|
14
|
+
linkedin_url: Types::Strict::String,
|
15
|
+
managed_by_employee_id: Types::Coercible::Int,
|
16
|
+
active: Types::Strict::Bool,
|
17
|
+
active_client_success_cycle_id: Types::Coercible::Int,
|
18
|
+
zendesk_id: Types::Coercible::String,
|
19
|
+
desk_id: Types::Coercible::String,
|
20
|
+
freshdesk_id: Types::Coercible::String,
|
21
|
+
jira_id: Types::Coercible::String,
|
22
|
+
terminated_date: Types::Strict::String, # TODO
|
23
|
+
assigned_sales_rep: Types::Coercible::Int,
|
24
|
+
salesforce_account_id: Types::Coercible::String,
|
25
|
+
usage_id: Types::Coercible::String,
|
26
|
+
street: Types::Strict::String,
|
27
|
+
state: Types::Strict::String,
|
28
|
+
country: Types::Strict::String,
|
29
|
+
city: Types::Strict::String,
|
30
|
+
external_id: Types::Coercible::String
|
31
|
+
)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
require_relative "../../types"
|
2
|
+
|
3
|
+
module ClientSuccess
|
4
|
+
module Schema
|
5
|
+
module Client
|
6
|
+
# TODO: upgrade dry types to use latest schema functions
|
7
|
+
Update = Types::Hash.schema(
|
8
|
+
external_id: Types::Coercible::String,
|
9
|
+
name: Types::Strict::String,
|
10
|
+
site_url: Types::Strict::String,
|
11
|
+
client_segment_id: Types::Coercible::Int,
|
12
|
+
zip: Types::Strict::String,
|
13
|
+
modified_by_employee_id: Types::Coercible::Int,
|
14
|
+
status_id: Types::Coercible::Int,
|
15
|
+
inception_date: Types::Strict::String, # TODO
|
16
|
+
created_by_employee: Types::Coercible::Int,
|
17
|
+
linkedin_url: Types::Strict::String,
|
18
|
+
managed_by_employee_id: Types::Coercible::Int,
|
19
|
+
active: Types::Strict::Bool,
|
20
|
+
success_score: Types::Strict::Int,
|
21
|
+
active_client_success_cycle_id: Types::Coercible::Int,
|
22
|
+
crm_customer_id: Types::Coercible::String,
|
23
|
+
crm_customer_url: Types::Strict::String,
|
24
|
+
zendesk_id: Types::Coercible::String,
|
25
|
+
desk_id: Types::Coercible::String,
|
26
|
+
freshdesk_id: Types::Coercible::String,
|
27
|
+
uservoice_id: Types::Coercible::String,
|
28
|
+
assigned_sales_rep: Types::Strict::String,
|
29
|
+
custom_field_values: Types::Strict::Array.default([]), # TODO
|
30
|
+
success_cycle_id: Types::Coercible::Int,
|
31
|
+
salesforce_account_id: Types::Coercible::String,
|
32
|
+
jira_id: Types::Coercible::String,
|
33
|
+
nps_score: Types::Strict::Int
|
34
|
+
)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|