yield_star_client 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (75) hide show
  1. data/.gitignore +8 -0
  2. data/.rspec +2 -0
  3. data/.rvmrc +3 -0
  4. data/Gemfile +4 -0
  5. data/README.md +38 -0
  6. data/Rakefile +17 -0
  7. data/lib/yield_star_client/amenity_methods.rb +77 -0
  8. data/lib/yield_star_client/client.rb +84 -0
  9. data/lib/yield_star_client/errors.rb +52 -0
  10. data/lib/yield_star_client/floor_plan_methods.rb +78 -0
  11. data/lib/yield_star_client/lease_term_rent_methods.rb +185 -0
  12. data/lib/yield_star_client/property_methods.rb +138 -0
  13. data/lib/yield_star_client/rent_methods.rb +179 -0
  14. data/lib/yield_star_client/unit_methods.rb +95 -0
  15. data/lib/yield_star_client/validations.rb +18 -0
  16. data/lib/yield_star_client/version.rb +3 -0
  17. data/lib/yield_star_client.rb +74 -0
  18. data/spec/fixtures/faults/authentication_fault.xml +15 -0
  19. data/spec/fixtures/faults/generic_fault.xml +9 -0
  20. data/spec/fixtures/faults/internal_error_fault.xml +15 -0
  21. data/spec/fixtures/faults/operation_fault.xml +15 -0
  22. data/spec/fixtures/get_available_units/multiple_floor_plans.xml +53 -0
  23. data/spec/fixtures/get_available_units/no_floor_plans.xml +11 -0
  24. data/spec/fixtures/get_available_units/single_floor_plan.xml +28 -0
  25. data/spec/fixtures/get_floor_plan/full_floor_plan.xml +19 -0
  26. data/spec/fixtures/get_floor_plan/simple_floor_plan.xml +14 -0
  27. data/spec/fixtures/get_floor_plan_amenities/multiple_amenities.xml +19 -0
  28. data/spec/fixtures/get_floor_plan_amenities/no_amenities.xml +10 -0
  29. data/spec/fixtures/get_floor_plan_amenities/single_amenity.xml +15 -0
  30. data/spec/fixtures/get_floor_plans/multiple_floor_plans.xml +28 -0
  31. data/spec/fixtures/get_floor_plans/no_floor_plan.xml +10 -0
  32. data/spec/fixtures/get_floor_plans/single_floor_plan.xml +15 -0
  33. data/spec/fixtures/get_lease_term_rent/multiple_rates.xml +41 -0
  34. data/spec/fixtures/get_lease_term_rent/no_rates.xml +13 -0
  35. data/spec/fixtures/get_lease_term_rent/single_rate.xml +21 -0
  36. data/spec/fixtures/get_lease_term_rent_plus/multiple_rates.xml +43 -0
  37. data/spec/fixtures/get_lease_term_rent_plus/no_rates.xml +14 -0
  38. data/spec/fixtures/get_lease_term_rent_plus/single_rate.xml +22 -0
  39. data/spec/fixtures/get_properties/multiple_properties.xml +38 -0
  40. data/spec/fixtures/get_properties/no_property.xml +10 -0
  41. data/spec/fixtures/get_properties/single_property.xml +14 -0
  42. data/spec/fixtures/get_property/full_property.xml +25 -0
  43. data/spec/fixtures/get_property/simple_property.xml +14 -0
  44. data/spec/fixtures/get_property_parameters/full_parameters.xml +38 -0
  45. data/spec/fixtures/get_property_parameters/no_parameters.xml +10 -0
  46. data/spec/fixtures/get_property_parameters/simple_parameters.xml +14 -0
  47. data/spec/fixtures/get_renewal_lease_term_rent/multiple_rates.xml +28 -0
  48. data/spec/fixtures/get_renewal_lease_term_rent/no_rates.xml +10 -0
  49. data/spec/fixtures/get_renewal_lease_term_rent/single_rate.xml +21 -0
  50. data/spec/fixtures/get_rent_summary/multiple_summaries.xml +41 -0
  51. data/spec/fixtures/get_rent_summary/no_summaries.xml +11 -0
  52. data/spec/fixtures/get_rent_summary/single_summary.xml +24 -0
  53. data/spec/fixtures/get_unit/full_unit.xml +22 -0
  54. data/spec/fixtures/get_unit/simple_unit.xml +16 -0
  55. data/spec/fixtures/get_unit_amenities/multiple_amenities.xml +20 -0
  56. data/spec/fixtures/get_unit_amenities/no_amenities.xml +11 -0
  57. data/spec/fixtures/get_unit_amenities/single_amenity.xml +15 -0
  58. data/spec/fixtures/get_units/multiple_units.xml +32 -0
  59. data/spec/fixtures/get_units/no_units.xml +10 -0
  60. data/spec/fixtures/get_units/single_unit.xml +16 -0
  61. data/spec/spec_helper.rb +16 -0
  62. data/spec/support/fault_handler_shared_examples.rb +68 -0
  63. data/spec/support/validator_shared_examples.rb +79 -0
  64. data/spec/yield_star_client/amenity_methods_spec.rb +165 -0
  65. data/spec/yield_star_client/client_spec.rb +150 -0
  66. data/spec/yield_star_client/errors_spec.rb +93 -0
  67. data/spec/yield_star_client/floor_plan_methods_spec.rb +126 -0
  68. data/spec/yield_star_client/lease_term_rent_methods_spec.rb +391 -0
  69. data/spec/yield_star_client/property_methods_spec.rb +189 -0
  70. data/spec/yield_star_client/rent_methods_spec.rb +271 -0
  71. data/spec/yield_star_client/unit_methods_spec.rb +168 -0
  72. data/spec/yield_star_client/validations_spec.rb +19 -0
  73. data/spec/yield_star_client_spec.rb +89 -0
  74. data/yield_star_client.gemspec +34 -0
  75. metadata +348 -0
data/.gitignore ADDED
@@ -0,0 +1,8 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ .yardoc/*
5
+ doc/*
6
+ *~
7
+ .DS_Store
8
+ Gemfile.lock
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --colour
2
+ --format progress
data/.rvmrc ADDED
@@ -0,0 +1,3 @@
1
+ branch_name=`git branch --no-color 2> /dev/null | sed -e '/^[^*]/d' -e 's/* \(.*\)/\1/'`
2
+ rvm --create use 1.8.7@yield_star_client-${branch_name}
3
+ #rvm --create use 1.9.2@yield_star_client-${branch_name}
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in yield_star_client.gemspec
4
+ gemspec
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ # YieldStar Client #
2
+
3
+ Client adapter for the YieldStar AppExchange web service.
4
+
5
+ ## Installation ##
6
+
7
+ The YieldStar adapter is available on [Rubygems][rubygems] and can be installed via:
8
+
9
+ gem install 'yield_star_client'
10
+
11
+ ## Configuration ##
12
+
13
+ You will probably only need to configure the username and password for connecting to the remote service:
14
+
15
+ YieldStarClient.configure do |config|
16
+ config.username = 'my_user'
17
+ config.password = 'my_pass'
18
+ end
19
+
20
+ Sensible defaults are provided for other configuration options. **TODO**: link to the docs for the rest of the config.
21
+
22
+ ## Examples ##
23
+
24
+ **TODO:** More thorough usage examples.
25
+
26
+ client = YieldStarClient::Client.new
27
+ client.get_properties('my_client_name')
28
+
29
+ **TODO:** Link to docs for more info.
30
+
31
+ ## More Information ##
32
+
33
+ * [YieldStar documentation][yieldstar-docs]
34
+ * [YieldStar WSDL][yieldstar-wsdl]
35
+
36
+ [rubygems]: http://rubygems.org/gems/yield_star_client
37
+ [yieldstar-docs]: http://rmsws.yieldstar.com/rmsws/doc/AppExchange/index.html
38
+ [yieldstar-wsdl]: http://rmsws.yieldstar.com/rmsws/AppExchange?wsdl
data/Rakefile ADDED
@@ -0,0 +1,17 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+ RSpec::Core::RakeTask.new(:spec)
6
+
7
+ task :default => :spec
8
+
9
+ namespace :doc do
10
+ require 'yard'
11
+ YARD::Rake::YardocTask.new do |task|
12
+ task.files = ['README.md', 'lib/**/*.rb']
13
+ task.options = [
14
+ '--markup', 'markdown',
15
+ ]
16
+ end
17
+ end
@@ -0,0 +1,77 @@
1
+ require 'yield_star_client/validations'
2
+ require 'modelish'
3
+
4
+ module YieldStarClient
5
+ # Represents a YieldStar amenity.
6
+ #
7
+ # All amenities are guaranteed to have a +name+ and +type+; +value+ is optional.
8
+ #
9
+ # @attr [String] name the name of the amenity
10
+ # @attr [String] type the type of the amenity
11
+ # @attr [Float[ value the value of the amenity
12
+ class Amenity < Modelish::Base
13
+ property :name
14
+ property :type
15
+ property :value, :type => Float
16
+ end
17
+
18
+ module AmenityMethods
19
+ include Validations
20
+
21
+ # Retrieves all of the amenities associated with a specific floor plan.
22
+ #
23
+ # @param [String] client_name the YieldStar client name
24
+ # @param [String] external_property_id the ID of the property where the floor plan is located
25
+ # @param [String] floor_plan_name the name of the floor plan
26
+ #
27
+ # @return [Array<YieldStarClient::Amenity>] list of amenities
28
+ #
29
+ # @raise [ArgumentError] when a required argument is missing or invalid
30
+ # @raise [YieldStarClient::AuthenticationError] when unable to authenticate to the web service
31
+ # @raise [YieldStarClient::OperationError] when the service raises an OperationError fault
32
+ # @raise [YieldStarClient::InternalError] when the service raises an InternalError fault
33
+ # @raise [YieldStarClient::ServerError] when any other server-side error occurs
34
+ def get_floor_plan_amenities(client_name, external_property_id, floor_plan_name)
35
+ validate_client_name!(client_name)
36
+ validate_external_property_id!(external_property_id)
37
+ validate_required!(:floor_plan_name => floor_plan_name)
38
+
39
+ response = send_soap_request(:get_floor_plan_amenities, :client_name => client_name,
40
+ :external_property_id => external_property_id,
41
+ :floor_plan_name => floor_plan_name)
42
+
43
+ amenities = response.to_hash[:get_floor_plan_amenities_response][:return][:amenity] || []
44
+ [amenities].flatten.collect { |a| Amenity.new(a) }
45
+ end
46
+
47
+ # Retrieves all of the amenities associated with a specific unit.
48
+ #
49
+ # @param [String] client_name the YieldStar client name
50
+ # @param [String] external_property_id the ID of the property where the floor plan is located
51
+ # @param [String] unit_name the name of the unit
52
+ # @param [optional,String] building the name of the building where the unit is located
53
+ #
54
+ # @return [Array<YieldStarClient::Amenity>] list of unit amenities
55
+ #
56
+ # @raise [ArgumentError] when a required argument is missing or invalid
57
+ # @raise [YieldStarClient::AuthenticationError] when unable to authenticate to the web service
58
+ # @raise [YieldStarClient::OperationError] when the service raises an OperationError fault
59
+ # @raise [YieldStarClient::InternalError] when the service raises an InternalError fault
60
+ # @raise [YieldStarClient::ServerError] when any other server-side error occurs
61
+ def get_unit_amenities(client_name, external_property_id, unit_name, building=nil)
62
+ validate_client_name!(client_name)
63
+ validate_external_property_id!(external_property_id)
64
+ validate_required!(:unit_name => unit_name)
65
+
66
+ body = {:client_name => client_name,
67
+ :external_property_id => external_property_id,
68
+ :unit_name => unit_name}
69
+ body[:building] = building if building
70
+
71
+ response = send_soap_request(:get_unit_amenities, body)
72
+
73
+ amenities = response.to_hash[:get_unit_amenities_response][:return][:amenity] || []
74
+ [amenities].flatten.collect { |a| Amenity.new(a) }
75
+ end
76
+ end
77
+ end
@@ -0,0 +1,84 @@
1
+ require 'savon'
2
+
3
+ require 'property_methods'
4
+ require 'floor_plan_methods'
5
+ require 'unit_methods'
6
+ require 'amenity_methods'
7
+ require 'rent_methods'
8
+ require 'lease_term_rent_methods'
9
+
10
+ require 'errors'
11
+
12
+ module YieldStarClient
13
+ # YieldStarClient::Client is the main object for connecting to the YieldStar AppExchange service.
14
+ # The interface strives to be SOAP-agnostic whenever possible; all inputs and outputs are pure ruby
15
+ # and no knowledge of SOAP is required in order to use the client.
16
+ class Client
17
+ include PropertyMethods
18
+ include FloorPlanMethods
19
+ include UnitMethods
20
+ include AmenityMethods
21
+ include RentMethods
22
+ include LeaseTermRentMethods
23
+
24
+ attr_writer *YieldStarClient::VALID_CONFIG_OPTIONS
25
+
26
+ YieldStarClient::VALID_CONFIG_OPTIONS.each do |opt|
27
+ define_method(opt) { get_value(opt) }
28
+ end
29
+
30
+ # Initializes the client. All options are truly optional; if the option
31
+ # is not supplied to this method, then it will be set based on the
32
+ # YieldStarClient configuration.
33
+ #
34
+ # @see YieldStarClient.configure
35
+ #
36
+ # @param [Hash] options
37
+ # @option options [String] :username The username for authenticating to the web service.
38
+ # @option options [String] :password The password for authenticating to the web service.
39
+ # @option options [String] :endpoint The address for connecting to the web service.
40
+ # @option options [String] :namespace The XML namespace to use for requests.
41
+ def initialize(options={})
42
+ options.each { |k,v| self.send("#{k}=", v) if self.respond_to?("#{k}=") }
43
+ end
44
+
45
+ private
46
+ # Sends a request directly to the SOAP service.
47
+ #
48
+ # @param [Symbol] soap_action the action to be invoked
49
+ # @param [Hash] soap_parameters the parameters to populate the request body
50
+ # @return [Savon::SOAP::Response]
51
+ def send_soap_request(soap_action,soap_parameters={})
52
+ begin
53
+ response = soap_client.request :wsdl, soap_action do
54
+ soap.element_form_default = :qualified
55
+ soap.body = { :request => soap_parameters }
56
+ end
57
+ rescue Savon::SOAP::Fault => f
58
+ raise ServerError.translate_fault(f)
59
+ end
60
+ end
61
+
62
+ # Sets up a SOAP client for sending SOAP requests directly.
63
+ #
64
+ # @return [Savon::Client]
65
+ def soap_client
66
+ Savon::Client.new do
67
+ wsdl.endpoint = self.endpoint.to_s
68
+ wsdl.namespace = self.namespace
69
+ http.auth.basic self.username, self.password
70
+ end
71
+ end
72
+
73
+ # Retrieves an attribute's value. If the attribute has not been set
74
+ # on this object, it is retrieved from the global configuration.
75
+ #
76
+ # @see YieldStarClient.configure
77
+ #
78
+ # @param [Symbol] attribute the name of the attribute
79
+ # @return [String] the value of the attribute
80
+ def get_value(attribute)
81
+ instance_variable_get("@#{attribute}") || YieldStarClient.send(attribute)
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,52 @@
1
+ module YieldStarClient
2
+ # Represents a server-side error returned by the YieldStar web service.
3
+ class ServerError < 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 YieldStarClient error.
17
+ #
18
+ # @param [Savon::SOAP::Fault] soap_error the error object raised by the soap client
19
+ # @return [YieldStarClient::ServerError] the corresponding YieldStarClient error
20
+ def self.translate_fault(soap_error)
21
+ fault = soap_error.to_hash[:fault]
22
+
23
+ # set up defaults
24
+ error_class = YieldStarClient::ServerError
25
+ fault_detail = {:code => fault[:faultcode], :message => fault[:faultstring]}
26
+
27
+ if detail = fault[:detail]
28
+ if detail.has_key?(:authentication_fault)
29
+ error_class = YieldStarClient::AuthenticationError
30
+ fault_detail = detail[:authentication_fault]
31
+ elsif detail.has_key?(:operation_fault)
32
+ error_class = YieldStarClient::OperationError
33
+ fault_detail = detail[:operation_fault]
34
+ elsif detail.has_key?(:internal_error_fault)
35
+ error_class = YieldStarClient::InternalError
36
+ fault_detail = detail[:internal_error_fault]
37
+ end
38
+ end
39
+
40
+ error_class.new(fault_detail[:message], fault_detail[:code])
41
+ end
42
+ end
43
+
44
+ # Represents an error in authenticating to the web service
45
+ class AuthenticationError < ServerError; end
46
+
47
+ # Represents an internal error in the web service
48
+ class InternalError < ServerError; end
49
+
50
+ # Represents an operation error in the web service
51
+ class OperationError < ServerError; end
52
+ end
@@ -0,0 +1,78 @@
1
+ require 'yield_star_client/validations'
2
+ require 'modelish'
3
+
4
+ module YieldStarClient
5
+ # Represents a floor plan in the YieldStar system.
6
+ #
7
+ # A floor plan is guaranteed to have an +external_property_id+ and +name+. All other attributes are
8
+ # optional.
9
+ #
10
+ # @attr [String] external_property_id the property ID of this floor plan
11
+ # @attr [String] name the name of this floor plan
12
+ # @attr [String] description the description of this floor plan
13
+ # @attr [Integer] square_feet the average square footage of this floor plan
14
+ # @attr [Integer] unit_count the number of units with this floor plan
15
+ # @attr [Float] bedrooms the bedroom count of the floor plan
16
+ # @attr [Float] bathrooms the bathroom count of the floor plan
17
+ class FloorPlan < Modelish::Base
18
+ property :external_property_id
19
+ property :name
20
+ property :description
21
+ property :square_feet, :type => Integer, :from => :square_footage
22
+ property :unit_count, :type => Integer
23
+ property :bedrooms, :type => Float, :from => :bed_rooms
24
+ property :bathrooms, :type => Float, :from => :bath_rooms
25
+ end
26
+
27
+ module FloorPlanMethods
28
+ include YieldStarClient::Validations
29
+
30
+ # Retrieves all floor plans for a particular property.
31
+ #
32
+ # @param [String] client_name the YieldStar client name
33
+ # @param [String] external_property_id the ID of the property
34
+ # @return [Array<YieldStarClient::FloorPlan>] list of floor plans
35
+ #
36
+ # @raise [ArgumentError] when client_name or external_property_id is missing or invalid
37
+ # @raise [YieldStarClient::AuthenticationError] when unable to authenticate to the web service
38
+ # @raise [YieldStarClient::OperationError] when the service raises an OperationError fault
39
+ # @raise [YieldStarClient::InternalError] when the service raises an InternalError fault
40
+ # @raise [YieldStarClient::ServerError] when any other server-side error occurs
41
+ def get_floor_plans(client_name, external_property_id)
42
+ validate_client_name!(client_name)
43
+ validate_external_property_id!(external_property_id)
44
+
45
+ response = send_soap_request(:get_floor_plans, :client_name => client_name, :external_property_id => external_property_id)
46
+
47
+ floor_plans = response.to_hash[:get_floor_plans_response][:return][:floor_plan] || []
48
+ floor_plans = [floor_plans].flatten
49
+
50
+ floor_plans.collect { |fp| FloorPlan.new(fp) }
51
+ end
52
+
53
+ # Retrieves a specific floor plan.
54
+ #
55
+ # @param [String] client_name the YieldStar client name
56
+ # @param [String] external_property_id the ID of the property
57
+ # @param [String] floor_plan_name the name of the floor plan
58
+ # @return [YieldStarClient::FloorPlan] the floor plan data
59
+ #
60
+ # @raise [ArgumentError] when a parameter is missing or invalid
61
+ # @raise [YieldStarClient::AuthenticationError] when unable to authenticate to the web service
62
+ # @raise [YieldStarClient::OperationError] when the service raises an OperationError fault
63
+ # @raise [YieldStarClient::InternalError] when the service raises an InternalError fault
64
+ # @raise [YieldStarClient::ServerError] when any other server-side error occurs
65
+ def get_floor_plan(client_name, external_property_id, floor_plan_name)
66
+ validate_client_name!(client_name)
67
+ validate_external_property_id!(external_property_id)
68
+ validate_required!(:floor_plan_name => floor_plan_name)
69
+
70
+ response = send_soap_request(:get_floor_plan, :client_name => client_name,
71
+ :external_property_id => external_property_id,
72
+ :name => floor_plan_name)
73
+ floor_plan = response.to_hash[:get_floor_plan_response][:return][:floor_plan]
74
+
75
+ FloorPlan.new(floor_plan)
76
+ end
77
+ end
78
+ end
@@ -0,0 +1,185 @@
1
+ require 'yield_star_client/validations'
2
+ require 'modelish'
3
+
4
+ module YieldStarClient
5
+ # Represents common unit rate information.
6
+ #
7
+ # @attr [String] external_property_id the ID of the property where the unit is located
8
+ # @attr [String] building the building in which the unit is located
9
+ # @attr [String] unit_number the unit number identifying this unit
10
+ # @attr [Integer] lease_term the length, in months, of the lease term
11
+ # @attr [Date] end_date the date the proposed lease will expire
12
+ # @attr [Integer] market_rent the market rent for the current lease
13
+ # @attr [Integer] final_rent the effective rent for the current lease
14
+ # @attr [true,false] best indicates whether this is the best (i.e. highest) rent
15
+ # for the unit; defaults to true
16
+ class UnitRate < Modelish::Base
17
+ property :external_property_id
18
+ property :building
19
+ property :unit_number
20
+ property :lease_term, :type => Integer
21
+ property :end_date, :type => Date
22
+ property :market_rent, :type => Integer
23
+ property :final_rent, :type => Integer
24
+ property :best, :type => lambda { |val| val.to_s.strip == 'true' }, :default => true
25
+ end
26
+
27
+ # Represents unit rate data for a combination of lease term
28
+ # and move-in date for a particular unit.
29
+ #
30
+ # @attr {see YieldStarClient::UnitRate}
31
+ # @attr [Date] make_ready_date the actual date the unit is made available
32
+ # @attr [Date] move_in_date the move-in date used in project optimum rents for the unit
33
+ # @attr [Integer] total_concession the total concession amount (defaults to 0)
34
+ # @attr [Integer] monthly_fixed_concession the monthly fixed concession amount (defaults to 0)
35
+ # @attr [Float] monthly_percent_concession the monthly concession percentage (defaults to 0.0)
36
+ # @attr [Float] months_concession the months concession (defaults to 0.0)
37
+ # @attr [Integer] one_time_fixed_concession the one time fixed concession (defaults to 0.0)
38
+ # @attr [Date] price_valid_end_date the last date for which the price is valid
39
+ class LeaseTermRent < UnitRate
40
+ property :make_ready_date, :type => Date
41
+ property :move_in_date, :type => Date
42
+ property :total_concession, :type => Integer, :default => 0
43
+ property :monthly_fixed_concession, :type => Integer, :default => 0
44
+ property :monthly_percent_concession, :type => Float, :default => 0.0
45
+ property :months_concession, :type => Float, :default => 0.0
46
+ property :one_time_fixed_concession, :type => Integer, :default => 0
47
+ property :price_valid_end_date, :type => Date, :from => :pv_end_date
48
+ end
49
+
50
+ # Represents rate data for a unit that is up for lease renewal.
51
+ #
52
+ # @attr {see YieldStarClient::UnitRate}
53
+ # @attr [Date] start_date the actual start date of the projected lease (this will only be
54
+ # present when a start date was passed in as input
55
+ class RenewalLeaseTermRent < UnitRate
56
+ property :start_date, :type => Date
57
+ end
58
+
59
+ # @private
60
+ class LeaseTermRentOptions < Modelish::Base
61
+ property :unit_number, :required => true, :max_length => 50
62
+ property :building, :max_length => 50
63
+ property :min_lease_term, :type => Integer, :validate_type => true
64
+ property :max_lease_term, :type => Integer, :validate_type => true
65
+ property :first_move_in_date, :type => Date, :validate_type => true
66
+ property :last_move_in_date, :type => Date, :validate_type => true
67
+ property :ready_for_move_in_date, :type => Date, :validate_type => true
68
+ property :unit_available_date, :type => Date, :validate_type => true
69
+ property :start_date, :type => Date, :validate_type => true
70
+
71
+ def to_request_hash
72
+ h = {}
73
+ self.class.properties.each do |name|
74
+ h[name] = self.send(name).to_s if self.send(name)
75
+ end
76
+ h
77
+ end
78
+ end
79
+
80
+ module LeaseTermRentMethods
81
+ include Validations
82
+
83
+ # Retrieves a matrix providing the specific rate for each combination of
84
+ # lease term and move-in date for a particular unit.
85
+ #
86
+ # @param [String] client_name the YieldStar client name
87
+ # @param [String] external_property_id the ID of the property where the unit is located
88
+ # @param [String] unit_number the unit_number that identifies the available unit
89
+ # @param [Hash] opts optional filters for lease term data
90
+ # @option opts [String] :building the building in which the unit is located
91
+ # @option opts [Integer] :min_lease_term the minimum lease term for the lease matrix projections
92
+ # @option opts [Integer] :max_lease_term the maximum lease term for the lease matrix projections
93
+ # @option opts [Date] :first_move_in_date the start of the move-in date range for projecting optimum rents
94
+ # @option opts [Date] :last_move_in_date the end of the move-in date range for projecting optimum rents
95
+ # @option opts [Date] :ready_for_move_in_date the date that the unit is made ready for occupancy
96
+ # @option opts [Date] :unit_available_date the first date that the unit is vacant
97
+ #
98
+ # @return [Array<YieldStarClient::LeaseTermRent>] unit rate data
99
+ #
100
+ # @raise [ArgumentError] when a required argument is missing or invalid
101
+ # @raise [YieldStarClient::AuthenticationError] when unable to authenticate to the web service
102
+ # @raise [YieldStarClient::OperationError] when the service raises an OperationError fault
103
+ # @raise [YieldStarClient::InternalError] when the service raises an InternalError fault
104
+ # @raise [YieldStarClient::ServerError] when any other server-side error occurs
105
+ def get_lease_term_rent(client_name, external_property_id, unit_number, opts={})
106
+ opts ||= {}
107
+ call_lease_term_rent_method(client_name,
108
+ external_property_id,
109
+ unit_number,
110
+ opts.merge(:request_element => :lease_term_rent_unit_request,
111
+ :soap_action => :get_lease_term_rent,
112
+ :response_element => :lease_term_rent_unit_response,
113
+ :result_class => LeaseTermRent))
114
+ end
115
+
116
+ # This method is identical to {#get_lease_term_rent}, but the return value also includes
117
+ # the last date for which the price is valid.
118
+ #
119
+ # {see #get_lease_term_rent}
120
+ def get_lease_term_rent_plus(client_name, external_property_id, unit_number, opts={})
121
+ opts ||= {}
122
+ call_lease_term_rent_method(client_name,
123
+ external_property_id,
124
+ unit_number,
125
+ opts.merge(:request_element => :lease_term_rent_unit_request,
126
+ :soap_action => :get_lease_term_rent_plus,
127
+ :response_element => :lease_term_rent_unit_plus_response,
128
+ :result_class => LeaseTermRent))
129
+ end
130
+
131
+ # Retrieves rate data for units that are within "Renewal Notice Days" of lease expiration,
132
+ # and those units for which renewal rates have been manually generated and accepted.
133
+ #
134
+ # @param [String] client_name the YieldStar client name
135
+ # @param [String] external_property_id the ID of the property where the unit is located
136
+ # @param [String] unit_number the unit_number that identifies the available unit
137
+ # @param [Hash] opts optional filters for lease term data
138
+ # @option opts [String] :building the building in which the unit is located
139
+ # @option opts [Integer] :min_lease_term the minimum lease term for the lease matrix projections
140
+ # @option opts [Integer] :max_lease_term the maximum lease term for the lease matrix projections
141
+ # @option opts [Date] :start_date the actual start date of the renewal
142
+ #
143
+ # @return [Array<YieldStarClient::RenewalLeaseTermRent>] the list of units up for renewal
144
+ #
145
+ # @raise {see #get_lease_term_rent}
146
+ def get_renewal_lease_term_rent(client_name, external_property_id, unit_number, opts={})
147
+ opts ||= {}
148
+ call_lease_term_rent_method(client_name,
149
+ external_property_id,
150
+ unit_number,
151
+ opts.merge(:request_element => :renewal_lease_term_rent_unit_request,
152
+ :soap_action => :get_renewal_lease_term_rent,
153
+ :response_element => :renewal_lease_term_rent_unit_response,
154
+ :result_class => RenewalLeaseTermRent))
155
+ end
156
+
157
+ private
158
+ def call_lease_term_rent_method(client_name, external_property_id, unit_number, opts={})
159
+ validate_client_name!(client_name)
160
+ validate_external_property_id!(external_property_id)
161
+
162
+ request_opts = opts.merge(:unit_number => unit_number)
163
+ request_opts.delete_if { |k,v| [:request_element, :soap_action, :response_element, :result_class].include?(k) }
164
+
165
+ lease_term_opts = LeaseTermRentOptions.new(request_opts.merge(:unit_number => unit_number))
166
+ lease_term_opts.validate!
167
+ request_params = {:client_name => client_name,
168
+ :external_property_id => external_property_id,
169
+ opts[:request_element] => lease_term_opts.to_request_hash}
170
+
171
+ response = send_soap_request(opts[:soap_action], request_params)
172
+ response_hash = response.to_hash["#{opts[:soap_action]}_response".to_sym][:return][opts[:response_element]] || {}
173
+
174
+ common_params = {:external_property_id => external_property_id.to_s}
175
+ common_params.merge!(response_hash.reject { |k,v| k == :unit_rate })
176
+
177
+ unit_rates = response_hash[:unit_rate] || []
178
+ unit_rates = [unit_rates].flatten
179
+
180
+ unit_rates.collect do |r|
181
+ opts[:result_class].new(common_params.merge(r))
182
+ end
183
+ end
184
+ end
185
+ end