reps_client 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +8 -0
- data/.rspec +1 -0
- data/.rvmrc +2 -0
- data/Gemfile +4 -0
- data/README.md +62 -0
- data/Rakefile +14 -0
- data/lib/reps_client.rb +12 -0
- data/lib/reps_client/client.rb +95 -0
- data/lib/reps_client/community.rb +23 -0
- data/lib/reps_client/configuration.rb +83 -0
- data/lib/reps_client/errors.rb +36 -0
- data/lib/reps_client/lead.rb +291 -0
- data/lib/reps_client/pick_list.rb +62 -0
- data/lib/reps_client/version.rb +3 -0
- data/reps_client.gemspec +36 -0
- data/spec/fixtures/faults/client_fault.xml +28 -0
- data/spec/fixtures/faults/invalid_enterprise_key_fault.xml +25 -0
- data/spec/fixtures/faults/server_fault.xml +25 -0
- data/spec/fixtures/get_communities/multiple_communities.xml +59 -0
- data/spec/fixtures/get_communities/single_community.xml +54 -0
- data/spec/fixtures/get_pick_lists/full_pick_lists.xml +100 -0
- data/spec/fixtures/get_pick_lists/single_prefix.xml +70 -0
- data/spec/fixtures/get_pick_lists/single_relationship_type.xml +70 -0
- data/spec/fixtures/get_pick_lists/single_source.xml +71 -0
- data/spec/fixtures/get_pick_lists/single_suffix.xml +70 -0
- data/spec/reps_client/client_spec.rb +217 -0
- data/spec/reps_client/community_spec.rb +139 -0
- data/spec/reps_client/configuration_spec.rb +132 -0
- data/spec/reps_client/errors_spec.rb +56 -0
- data/spec/reps_client/lead_spec.rb +906 -0
- data/spec/reps_client/pick_list_spec.rb +320 -0
- data/spec/reps_client_spec.rb +11 -0
- data/spec/spec_helper.rb +21 -0
- data/spec/support/fault_handler_shared_examples.rb +51 -0
- data/spec/support/lead_shared_examples.rb +33 -0
- data/spec/support/pick_list_shared_examples.rb +16 -0
- metadata +259 -0
data/.gitignore
ADDED
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--colour
|
data/.rvmrc
ADDED
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
# REPS Client #
|
2
|
+
|
3
|
+
This adapter provides a simple wrapper around a SOAP client for the [MDI Achieve][mdi] REPS Leads web service.
|
4
|
+
|
5
|
+
## Installation ##
|
6
|
+
|
7
|
+
To use this library prior to the initial release, add this to your Gemfile:
|
8
|
+
|
9
|
+
gem 'reps_client', :git => 'git@github.com:g5search/reps_client.git', :branch => 'development'
|
10
|
+
|
11
|
+
## Basics ##
|
12
|
+
|
13
|
+
For more details on any topic, see the [RDocs][rdocs].
|
14
|
+
|
15
|
+
### Configuration ###
|
16
|
+
|
17
|
+
Most commonly, you will only need to supply the enterprise key in order to access the service.
|
18
|
+
|
19
|
+
Configuration options can be set at the module level to automatically apply it to all client instances:
|
20
|
+
|
21
|
+
RepsClient.configure do |config|
|
22
|
+
config.enterprise_key = 'mykey'
|
23
|
+
end
|
24
|
+
|
25
|
+
client = RepsClient::Client.new
|
26
|
+
|
27
|
+
Or you can set it on each individual client instance:
|
28
|
+
|
29
|
+
client = RepsClient::Client.new(:enterprise_key => 'mykey')
|
30
|
+
|
31
|
+
### Examples ###
|
32
|
+
|
33
|
+
To retrieve a list of communities that belong to this enterprise:
|
34
|
+
|
35
|
+
communities = client.get_communities
|
36
|
+
# => [#<RepsClient::Community address1="123 Anywhere Ln" city="Somewhere" community_id="2" name="Pine View Terrace" state="AK" zip="12345">, #<RepsClient::Community community_id="8" name="The Hills at Dale Valley">]
|
37
|
+
|
38
|
+
To retrieve a list of enumerated data types (e.g. relationship type, ad source) that are available for a particular community:
|
39
|
+
|
40
|
+
pick_lists = client.get_pick_lists(2)
|
41
|
+
# => {:prefix => [#<RepsClient::Prefix prefix_id="1" value="Mr.">, #<RepsClient::Prefix prefix_id="2" value="Ms.">],
|
42
|
+
# :suffix => [#<RepsClient::Suffix suffix_id="200" value="Jr.">, #<RepsClient::Suffix suffix_id="99" value="M.D">],
|
43
|
+
# :relationship_type => [#<RepsClient::RelationshipType relationship_type_id="42" name="Self">],
|
44
|
+
# :source => [#<RepsClient::Source source_id="99" code="WEB" description="From the community website">]}
|
45
|
+
|
46
|
+
To save a lead, which include a contact and prospect. A very simple lead might look like this:
|
47
|
+
|
48
|
+
contact = RepsClient::Contact.new(:prefix => 'Mr.',
|
49
|
+
:first_name => 'Fred',
|
50
|
+
:last_name => 'Rogers',
|
51
|
+
:email => 'misterrogers@neighborhood.com',
|
52
|
+
:relationship_to_prospect_id => 2,
|
53
|
+
:source_id => 99)
|
54
|
+
prospect = RepsClient::Prospect.new(:prefix => 'Mr.',
|
55
|
+
:first_name => 'Fred',
|
56
|
+
:last_name => 'Rogers',
|
57
|
+
:email => 'misterrogers@neighborhood.com',
|
58
|
+
:notes => 'Request for Brochure')
|
59
|
+
client.save_lead(2, contact, prospect)
|
60
|
+
|
61
|
+
[mdi]: http://mdiachieve.com
|
62
|
+
[rdocs]: http://rubydoc.info/gems/reps_client
|
data/Rakefile
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'bundler/gem_tasks'
|
2
|
+
|
3
|
+
require 'rspec/core/rake_task'
|
4
|
+
RSpec::Core::RakeTask.new(:spec)
|
5
|
+
|
6
|
+
task :default => :spec
|
7
|
+
|
8
|
+
namespace :doc do
|
9
|
+
require 'yard'
|
10
|
+
YARD::Rake::YardocTask.new do |task|
|
11
|
+
task.files = ['README.md', 'lib/**/*.rb']
|
12
|
+
task.options = ['--markup', 'markdown']
|
13
|
+
end
|
14
|
+
end
|
data/lib/reps_client.rb
ADDED
@@ -0,0 +1,95 @@
|
|
1
|
+
require 'savon'
|
2
|
+
|
3
|
+
require 'reps_client/community'
|
4
|
+
require 'reps_client/errors'
|
5
|
+
require 'reps_client/pick_list'
|
6
|
+
require 'reps_client/lead'
|
7
|
+
|
8
|
+
module RepsClient
|
9
|
+
# TODO: document RepsClient::Client
|
10
|
+
class Client
|
11
|
+
include CommunityMethods
|
12
|
+
include PickListMethods
|
13
|
+
include LeadMethods
|
14
|
+
|
15
|
+
# Mutators for configuration options
|
16
|
+
attr_writer *RepsClient::VALID_CONFIG_OPTIONS
|
17
|
+
|
18
|
+
# Accessors for configuration options
|
19
|
+
RepsClient::VALID_CONFIG_OPTIONS.each do |opt|
|
20
|
+
define_method(opt) { get_value(opt) }
|
21
|
+
end
|
22
|
+
|
23
|
+
# Initializes the client.
|
24
|
+
#
|
25
|
+
# @param [Hash] options
|
26
|
+
# @option options [String] :username The username for authenticating to the web service
|
27
|
+
# @option options [String] :password The password for authenticating to the web service
|
28
|
+
# @option options [String] :enterprise_key The enterprise key for authentication to the web service
|
29
|
+
# @option options [String] :endpoint The address for connecting to the web service
|
30
|
+
# @option options [String] :namespace The XML namespace to use for requests
|
31
|
+
def initialize(options={})
|
32
|
+
options.each { |k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") }
|
33
|
+
end
|
34
|
+
|
35
|
+
# The raw SOAP client to directly execute requests against the REPS service.
|
36
|
+
# Preconfigures all service-wide endpoints, namespace URLs, credentials, etc.
|
37
|
+
# This method is provided as a convenience to developers; it should rarely be
|
38
|
+
# used directly.
|
39
|
+
#
|
40
|
+
# @return [Savon::Client] the SOAP client
|
41
|
+
def soap_client
|
42
|
+
Savon::Client.new do
|
43
|
+
wsdl.endpoint = self.endpoint.to_s
|
44
|
+
wsdl.namespace = self.namespace.to_s
|
45
|
+
wsse.credentials self.username, self.password, false
|
46
|
+
|
47
|
+
# We have to override the wsse timestamp method to force UTC
|
48
|
+
# (the reps service cacks on any other timezone)
|
49
|
+
class << wsse
|
50
|
+
define_method(:timestamp, lambda { @timestamp ||= Time.now.utc.xs_datetime })
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
# Sends a SOAP request to the remote service. This method takes care of
|
56
|
+
# constructing the SOAP envelope and headers as well as common parameters
|
57
|
+
# for REPS (e.g. the enterprise key)
|
58
|
+
#
|
59
|
+
# @param [Symbol] soap_action the name of the soap action to invoke (in snake-case, e.g. ":my_soap_action")
|
60
|
+
# @param [Hash] soap_parameters the input parameters for the soap action. All symbolic keys will
|
61
|
+
# converted to strings in lowerCamelCase (e.g. :my_soap_param becomes
|
62
|
+
# 'mySoapParam'); no conversion is performed on string keys.
|
63
|
+
# @return [Savon::SOAP::Response] the response from the service
|
64
|
+
def send_soap_request(soap_action,soap_parameters={})
|
65
|
+
begin
|
66
|
+
# The service requires that the soap action be in capitalized camelcase
|
67
|
+
# (e.g. 'GetCommunities') but the rest of the XML elements need to be in
|
68
|
+
# lower camelcase (e.g. 'enterpriseKey'). So we handle the soap_action
|
69
|
+
# format ourselves and retain Gyoku's default lower camelcase translation
|
70
|
+
# for everything else
|
71
|
+
camelcase_action = Gyoku::XMLKey.create(soap_action).gsub(/^[a-z]/) { |m| m.upcase }
|
72
|
+
|
73
|
+
response = soap_client.request :wsdl, camelcase_action do
|
74
|
+
soap.element_form_default = :qualified
|
75
|
+
soap.body = {:enterprise_key => self.enterprise_key}.merge(soap_parameters)
|
76
|
+
http.headers['SOAPAction'] = %{"#{URI.join(self.namespace, camelcase_action)}"}
|
77
|
+
end
|
78
|
+
rescue Savon::SOAP::Fault => f
|
79
|
+
raise RepsClient::ServiceError.translate_fault(f)
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
|
84
|
+
# Retrieves an attribute value. If the attribute has not been set
|
85
|
+
# on this object, it is retrieved from the global configuration.
|
86
|
+
#
|
87
|
+
# @see RepsClient.configure
|
88
|
+
#
|
89
|
+
# @param [Symbol] attribute the name of the attribute
|
90
|
+
# @return [String] the value of the attribute
|
91
|
+
def get_value(attribute)
|
92
|
+
instance_variable_get("@#{attribute}") || RepsClient.send(attribute)
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'modelish'
|
2
|
+
|
3
|
+
module RepsClient
|
4
|
+
# A community (i.e. location) as configured in the MDI REPS service.
|
5
|
+
class Community < Modelish::Base
|
6
|
+
property :community_id, :from => :community_idy, :type => Integer
|
7
|
+
property :name, :type => String
|
8
|
+
property :address1, :from => :community_address1, :type => String
|
9
|
+
property :address2, :from => :community_address2, :type => String
|
10
|
+
property :city, :from => :community_city, :type => String
|
11
|
+
property :state, :from => :community_state, :type => String
|
12
|
+
property :zip, :from => :community_zip, :type => String
|
13
|
+
end
|
14
|
+
|
15
|
+
module CommunityMethods
|
16
|
+
def get_communities
|
17
|
+
response = send_soap_request(:get_communities)
|
18
|
+
communities = response.to_hash[:get_communities_response][:get_communities_result][:diffgram][:document_element][:community]
|
19
|
+
communities ||= []
|
20
|
+
[communities].flatten.collect { |c| Community.new(c) }
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
require 'configlet'
|
2
|
+
|
3
|
+
module RepsClient
|
4
|
+
# All valid configurations options
|
5
|
+
VALID_CONFIG_OPTIONS = [:endpoint, :username, :password, :namespace, :enterprise_key]
|
6
|
+
|
7
|
+
DEFAULT_ENDPOINT = 'https://repssuite.mdiachieve.com/webservices/lead.asmx?wsdl'
|
8
|
+
DEFAULT_NAMESPACE = 'http://www.mdiachieve.com/'
|
9
|
+
|
10
|
+
module Configuration
|
11
|
+
include Configlet
|
12
|
+
|
13
|
+
def self.extended(base)
|
14
|
+
# Default configuration - happens whether or not .configure is called
|
15
|
+
base.config :reps_client do
|
16
|
+
default :endpoint => DEFAULT_ENDPOINT
|
17
|
+
default :namespace => DEFAULT_NAMESPACE
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# Mutators and accessors for configuration options
|
22
|
+
VALID_CONFIG_OPTIONS.each do |config_opt|
|
23
|
+
define_method(config_opt) do
|
24
|
+
self[config_opt]
|
25
|
+
end
|
26
|
+
|
27
|
+
define_method("#{config_opt}=".to_sym) do |val|
|
28
|
+
self[config_opt] = val
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
# Configures this module through the given +block+.
|
33
|
+
# Default configuration options will be applied unless
|
34
|
+
# they are explicitly overridden in the +block+.
|
35
|
+
#
|
36
|
+
# @yield [_self] configures service connection options
|
37
|
+
# @yieldparam [YieldstarClient] _self the object on which the configure method was called
|
38
|
+
# @example Typical case utilizing defaults
|
39
|
+
# RepsClient.configure do |config|
|
40
|
+
# config.username = 'my_user'
|
41
|
+
# config.password = 'my_pass'
|
42
|
+
# config.enterprise_key = 'my_key'
|
43
|
+
# end
|
44
|
+
# @example Overriding defaults
|
45
|
+
# RepsClient.configure do |config|
|
46
|
+
# config.username = 'my_user'
|
47
|
+
# config.password = 'my_pass'
|
48
|
+
# config.endpoint = 'http://my.endpoint.com'
|
49
|
+
# config.namespace = 'http://my.namespace.com'
|
50
|
+
# config.enterprise_key = 'my_key'
|
51
|
+
# end
|
52
|
+
# @return [RepsClient] _self
|
53
|
+
# @see VALID_CONFIG_OPTIONS
|
54
|
+
def configure
|
55
|
+
config :reps_client do
|
56
|
+
yield self
|
57
|
+
end
|
58
|
+
|
59
|
+
self
|
60
|
+
end
|
61
|
+
|
62
|
+
# Create a hash of configuration options and their
|
63
|
+
# values.
|
64
|
+
#
|
65
|
+
# @return [Hash<Symbol,Object>] the options hash
|
66
|
+
def options
|
67
|
+
VALID_CONFIG_OPTIONS.inject({}) do |option, key|
|
68
|
+
option.merge!(key => send(key))
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
# Resets this module's configuration.
|
73
|
+
# Configuration options will be set to default values
|
74
|
+
# if they exist; otherwise, they will be set to nil.
|
75
|
+
#
|
76
|
+
# @see VALID_CONFIG_OPTIONS
|
77
|
+
# @see DEFAULT_ENDPOINT
|
78
|
+
# @see DEFAULT_NAMESPACE
|
79
|
+
def reset
|
80
|
+
VALID_CONFIG_OPTIONS.each { |opt| self.send("#{opt}=", nil) }
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module RepsClient
|
2
|
+
# Represents a server-side error returned by the REPS web service.
|
3
|
+
class ServiceError < StandardError
|
4
|
+
attr_reader :code
|
5
|
+
|
6
|
+
# Creates a new error object.
|
7
|
+
#
|
8
|
+
# @param [String] message the error message. If no message is supplied, the
|
9
|
+
# object's class name will be used as the message.
|
10
|
+
# @param [String] code the error code
|
11
|
+
def initialize(message=nil, code=nil)
|
12
|
+
super(message)
|
13
|
+
@code = code
|
14
|
+
end
|
15
|
+
|
16
|
+
# Translates a soap fault into the appropriate RepsClient error.
|
17
|
+
#
|
18
|
+
# @param [Savon::SOAP::Fault] soap_error the error object raised by the soap client
|
19
|
+
# @return [RepsClient::ServiceError] the corresponding RepsClient error
|
20
|
+
def self.translate_fault(soap_error)
|
21
|
+
fault = soap_error.to_hash[:fault]
|
22
|
+
|
23
|
+
# set up defaults
|
24
|
+
error_class = RepsClient::ServiceError
|
25
|
+
|
26
|
+
if fault[:faultcode] == 'InvalidEnterpriseKey'
|
27
|
+
error_class = RepsClient::InvalidEnterpriseKeyError
|
28
|
+
end
|
29
|
+
|
30
|
+
error_class.new(fault[:faultstring], fault[:faultcode])
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# Represents an error in the enterprise key sent to the REPS service
|
35
|
+
class InvalidEnterpriseKeyError < ServiceError; end
|
36
|
+
end
|
@@ -0,0 +1,291 @@
|
|
1
|
+
require 'modelish'
|
2
|
+
|
3
|
+
module RepsClient
|
4
|
+
# The person who is the primary contact for a lead.
|
5
|
+
#
|
6
|
+
# Minimally, a Contact is required to have a first name,
|
7
|
+
# last name, and some means of contacting them (email, phone,
|
8
|
+
# or mailing address). All other attributes are optional.
|
9
|
+
#
|
10
|
+
# @example Creating a valid contact with an email address
|
11
|
+
# contact = RepsClient::Contact.new(:first_name => 'Alice',
|
12
|
+
# :last_name => 'Aardvark',
|
13
|
+
# :email => 'alice@aardvark.com')
|
14
|
+
#
|
15
|
+
# @example Creating a valid contact with a phone number
|
16
|
+
# contact = RepsClient::Contact.new(:first_name => 'Bob',
|
17
|
+
# :last_name => 'Builder',
|
18
|
+
# :phone => '5551234567')
|
19
|
+
#
|
20
|
+
# @example Creating a valid contact with a mailing address
|
21
|
+
# contact = RepsClient::Contact.new(:first_name => 'Charleston',
|
22
|
+
# :last_name => 'Chew',
|
23
|
+
# :address1 => '123 Gumdrop Ct',
|
24
|
+
# :city => 'Candyland',
|
25
|
+
# :state => 'CA',
|
26
|
+
# :zip_code => '12345')
|
27
|
+
class Contact < Modelish::Base
|
28
|
+
# @attribute [rw]
|
29
|
+
# @return [String] the contact's salutation (e.g. "Mr.", "Ms.", "Dr.", etc.)
|
30
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
31
|
+
property :prefix, :type => String, :max_length => 30
|
32
|
+
|
33
|
+
# @attribute [rw]
|
34
|
+
# @return [String] the contact's first name
|
35
|
+
# @note This attribute is required on initialization.
|
36
|
+
property :first_name, :type => String, :required => true, :max_length => 30
|
37
|
+
|
38
|
+
# @attribute [rw]
|
39
|
+
# @return [String] the contact's middle name or initial
|
40
|
+
property :middle_name, :type => String, :max_length => 30
|
41
|
+
|
42
|
+
# @attribute [rw]
|
43
|
+
# @return [String] the contact's last name
|
44
|
+
# @note This attribute is required on initialization.
|
45
|
+
property :last_name, :type => String, :required => true, :max_length => 30
|
46
|
+
|
47
|
+
# @attribute [rw]
|
48
|
+
# @return [String] the contact's name suffix (e.g. 'Jr.', 'M.D.', etc.)
|
49
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
50
|
+
|
51
|
+
property :suffix, :type => String, :max_length => 30
|
52
|
+
|
53
|
+
# @attribute [rw]
|
54
|
+
# @return [String] the first line of the contact's street address
|
55
|
+
# @note This attribute is only required when there is no phone or email.
|
56
|
+
property :address1, :type => String, :max_length => 100
|
57
|
+
|
58
|
+
# @attribute [rw]
|
59
|
+
# @return [String] the second line of the contact's street address
|
60
|
+
property :address2, :type => String, :max_length => 100
|
61
|
+
|
62
|
+
# @attribute [rw]
|
63
|
+
# @return [String] the city for the contact's mailing address
|
64
|
+
property :city, :type => String, :max_length => 50
|
65
|
+
|
66
|
+
# @attribute [rw]
|
67
|
+
# @return [String] the state code for the contact's mailing address
|
68
|
+
property :state, :type => String, :max_length => 2
|
69
|
+
|
70
|
+
# @attribute [rw]
|
71
|
+
# @return [String] the zip code for the contact's mailing address
|
72
|
+
property :zip_code, :type => String, :max_length => 10
|
73
|
+
|
74
|
+
# @attribute [rw]
|
75
|
+
# @return [String] the country from the contact's mailing address
|
76
|
+
property :country, :type => String
|
77
|
+
|
78
|
+
# @attribute [rw]
|
79
|
+
# @return [String] the contact's phone number
|
80
|
+
property :phone, :type => String, :max_length => 20
|
81
|
+
|
82
|
+
# @attribute [rw]
|
83
|
+
# @return [String] the contact's phone number extension
|
84
|
+
property :phone_extension, :type => String, :max_length => 5
|
85
|
+
|
86
|
+
# @attribute [rw]
|
87
|
+
# @return [String] the contact's email address
|
88
|
+
property :email, :type => String, :max_length => 100
|
89
|
+
|
90
|
+
# @attribute [rw]
|
91
|
+
# @return [int] the relationship type id describing the contact's relationship to the prospect
|
92
|
+
# @note The relationship type is determined based on the contact's answer to the question 'What
|
93
|
+
# is your relationship to the prospect?' For instance, if a contact was acting on behalf of their
|
94
|
+
# mother, the relationship type name might be 'Child'. Valid relationship types are available from
|
95
|
+
# the remote service.
|
96
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
97
|
+
property :relationship_to_prospect_id, :type => Integer
|
98
|
+
|
99
|
+
# @attribute [rw]
|
100
|
+
# @return [true,false] contact opted in to mailings (defaults to false)
|
101
|
+
property :include_in_mailings, :default => false, :type => lambda { |v| !!v }
|
102
|
+
|
103
|
+
# @attribute [rw]
|
104
|
+
# @return [true,false] contact opted in to mailings (defaults to false)
|
105
|
+
property :include_in_emailings, :default => false, :type => lambda { |v| !!v }
|
106
|
+
|
107
|
+
# @attribute [rw]
|
108
|
+
# @return [int]
|
109
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
110
|
+
# @note This attribute is required on initialization.
|
111
|
+
property :source_id, :type => Integer, :required => true, :validate_type => true
|
112
|
+
|
113
|
+
# Validates attributes (including contact method), returning errors.
|
114
|
+
# @see http://rubydoc.info/gems/modelish/Modelish/Validations#validate-instance_method
|
115
|
+
def validate
|
116
|
+
errors = super
|
117
|
+
[:phone, :email, :address1, :city, :state, :zip_code].each do |k|
|
118
|
+
errors[k] ||= []
|
119
|
+
errors[k] << contact_method_error
|
120
|
+
end unless has_contact_method?
|
121
|
+
errors
|
122
|
+
end
|
123
|
+
|
124
|
+
# Validates attributes (including contact method), raising errors.
|
125
|
+
# @see http://rubydoc.info/gems/modelish/Modelish/Validations#validate%21-instance_method
|
126
|
+
def validate!
|
127
|
+
super
|
128
|
+
raise contact_method_error unless has_contact_method?
|
129
|
+
end
|
130
|
+
|
131
|
+
# Checks that at least one contact method has been supplied.
|
132
|
+
# Possible contact methods include email, phone, and mailing address.
|
133
|
+
#
|
134
|
+
# @return [true,false] true if there is at least one contact method; false otherwise
|
135
|
+
def has_contact_method?
|
136
|
+
!(phone.blank? && email.blank? && (address1.blank? || city.blank? || state.blank? || zip_code.blank?))
|
137
|
+
end
|
138
|
+
|
139
|
+
# @private
|
140
|
+
# Wrangle the model into a format that the service will accept
|
141
|
+
def to_soap_hash
|
142
|
+
hash = {:order! => []}
|
143
|
+
|
144
|
+
[:prefix, :first_name, :middle_name, :last_name, :suffix,
|
145
|
+
:address1, :address2, :city, :state, :zip_code, :country,
|
146
|
+
:phone, :phone_extension, :email, :relationship_to_prospect_id,
|
147
|
+
:include_in_mailings, :include_in_emailings, :source_id].each do |prop|
|
148
|
+
val = self.send(prop)
|
149
|
+
|
150
|
+
unless val.nil?
|
151
|
+
key = prop == :source_id ? 'SourceIDY' : prop.to_s.camelcase
|
152
|
+
hash[key] = val
|
153
|
+
hash[:order!] << key
|
154
|
+
end
|
155
|
+
end
|
156
|
+
|
157
|
+
hash
|
158
|
+
end
|
159
|
+
|
160
|
+
private
|
161
|
+
def contact_method_error
|
162
|
+
ArgumentError.new('Must have one or more of the following: phone, email, or mailing address.')
|
163
|
+
end
|
164
|
+
end
|
165
|
+
|
166
|
+
# The person on whose behalf the lead was submitted; the prospective resident.
|
167
|
+
class Prospect < Modelish::Base
|
168
|
+
# @attribute [rw]
|
169
|
+
# @return [String] the prospect's salutation (e.g. 'Mr.', 'Ms.', 'Dr.', etc.)
|
170
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
171
|
+
property :prefix, :type => String, :max_length => 30
|
172
|
+
|
173
|
+
# @attribute [rw]
|
174
|
+
# @return [String] the prospect's first name
|
175
|
+
property :first_name, :type => String, :max_length => 30
|
176
|
+
|
177
|
+
# @attribute [rw]
|
178
|
+
# @return [String] the prospect's middle name
|
179
|
+
property :middle_name, :type => String, :max_length => 30
|
180
|
+
|
181
|
+
# @attribute [rw]
|
182
|
+
# @return [String] the prospect's last name
|
183
|
+
property :last_name, :type => String, :max_length => 30
|
184
|
+
|
185
|
+
# @attribute [rw]
|
186
|
+
# @return [String] the prospect's name suffix (e.g. 'Jr.', 'M.D.', etc.)
|
187
|
+
# @see RepsClient::PickListMethods#get_pick_lists
|
188
|
+
property :suffix, :type => String, :max_length => 30
|
189
|
+
|
190
|
+
# @attribute [rw]
|
191
|
+
# @return [String] the prospect's nickname
|
192
|
+
property :nickname, :type => String, :max_length => 30
|
193
|
+
|
194
|
+
# @attribute [rw]
|
195
|
+
# @return [String] the first line of the prospect's street address
|
196
|
+
property :address1, :type => String, :max_length => 100
|
197
|
+
|
198
|
+
# @attribute [rw]
|
199
|
+
# @return [String] the second line of the prospect's street address
|
200
|
+
property :address2, :type => String, :max_length => 100
|
201
|
+
|
202
|
+
# @attribute [rw]
|
203
|
+
# @return [String] the city for the prospect's mailing address
|
204
|
+
property :city, :type => String, :max_length => 50
|
205
|
+
|
206
|
+
# @attribute [rw]
|
207
|
+
# @return [String] the state code for the prospect's mailing address
|
208
|
+
property :state, :type => String, :max_length => 2
|
209
|
+
|
210
|
+
# @attribute [rw]
|
211
|
+
# @return [String] the zip code for the prospect's mailing address
|
212
|
+
property :zip_code, :type => String, :max_length => 10
|
213
|
+
|
214
|
+
# @attribute [rw]
|
215
|
+
# @return [String] the country for the prospect's mailing address
|
216
|
+
property :country, :type => String
|
217
|
+
|
218
|
+
# @attribute [rw]
|
219
|
+
# @return [String] the prospect's phone number
|
220
|
+
property :phone, :type => String, :max_length => 20
|
221
|
+
|
222
|
+
# @attribute [rw]
|
223
|
+
# @return [String] the prospect's phone extension
|
224
|
+
property :phone_extension, :type => String, :max_length => 5
|
225
|
+
|
226
|
+
# @attribute [rw]
|
227
|
+
# @return [String] the prospect's email address
|
228
|
+
property :email, :type => String, :max_length => 100
|
229
|
+
|
230
|
+
# @attribute [rw]
|
231
|
+
# @return [String] notes on the prospect (maximum 250 characters)
|
232
|
+
property :notes, :type => String
|
233
|
+
|
234
|
+
# @attribute [rw]
|
235
|
+
# @return [true,false] true if prospect opts in to mailings, false otherwise (defaults to false)
|
236
|
+
property :include_in_mailings, :default => false, :type => lambda { |v| !!v }
|
237
|
+
|
238
|
+
# @attribute [rw]
|
239
|
+
# @return [true,false] true if prospect opts in to emailings, false otherwise (defaults to false)
|
240
|
+
property :include_in_emailings, :default => false, :type => lambda { |v| !!v }
|
241
|
+
|
242
|
+
# @private
|
243
|
+
# Wrangle the model into a format that the service will accept
|
244
|
+
def to_soap_hash
|
245
|
+
hash = { :order! => [] }
|
246
|
+
|
247
|
+
[:prefix, :first_name, :middle_name, :last_name, :suffix, :nickname,
|
248
|
+
:address1, :address2, :city, :state, :zip_code, :country,
|
249
|
+
:phone, :phone_extension, :email, :notes, :include_in_mailings,
|
250
|
+
:include_in_emailings].each do |prop|
|
251
|
+
val = self.send(prop)
|
252
|
+
unless val.nil?
|
253
|
+
key = prop.to_s.camelcase
|
254
|
+
hash[key] = val
|
255
|
+
hash[:order!] << key
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
hash
|
260
|
+
end
|
261
|
+
end
|
262
|
+
|
263
|
+
module LeadMethods
|
264
|
+
include Modelish::Validations
|
265
|
+
|
266
|
+
# Submit a new lead to the remote REPS service.
|
267
|
+
# Each lead must have a contact and community_id.
|
268
|
+
#
|
269
|
+
# @param [Integer] community_id the REPS ID of the community
|
270
|
+
# @param [RepsClient::Contact] contact the contact person for the lead
|
271
|
+
# @param [RepsClient::Prospect] prospect the prospective resident (if different than contact)
|
272
|
+
#
|
273
|
+
def save_lead(community_id,contact,prospect=nil)
|
274
|
+
LeadMethods.validate_required!(:community_id => community_id,
|
275
|
+
:contact => contact)
|
276
|
+
LeadMethods.validate_type!(:community_id, community_id, Integer)
|
277
|
+
|
278
|
+
contact.validate!
|
279
|
+
soap_params = {:community_id => community_id,
|
280
|
+
:new_contact => contact.to_soap_hash,
|
281
|
+
:order! => [:enterprise_key, :community_id, :new_contact] }
|
282
|
+
if prospect
|
283
|
+
prospect.validate!
|
284
|
+
soap_params[:new_prospect] = prospect.to_soap_hash
|
285
|
+
soap_params[:order!] << :new_prospect
|
286
|
+
end
|
287
|
+
|
288
|
+
send_soap_request(:save_lead, soap_params)
|
289
|
+
end
|
290
|
+
end
|
291
|
+
end
|