reps_client 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|