yield_star_client 0.1.0

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.
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