real_page 2.3.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 (95) hide show
  1. checksums.yaml +7 -0
  2. data/.ci +139 -0
  3. data/.gitignore +3 -0
  4. data/.rakeTasks +7 -0
  5. data/.rspec +3 -0
  6. data/CHANGELOG.txt +12 -0
  7. data/CODEOWNERS +1 -0
  8. data/CODE_OF_CONDUCT.md +13 -0
  9. data/Gemfile +6 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +588 -0
  12. data/Rakefile +7 -0
  13. data/bin/console +15 -0
  14. data/bin/setup +7 -0
  15. data/config/multi_xml.rb +4 -0
  16. data/lib/real_page.rb +54 -0
  17. data/lib/real_page/attribute_parser.rb +48 -0
  18. data/lib/real_page/attribute_parser/base.rb +21 -0
  19. data/lib/real_page/attribute_parser/boolean.rb +25 -0
  20. data/lib/real_page/attribute_parser/date.rb +28 -0
  21. data/lib/real_page/attribute_parser/date_time.rb +23 -0
  22. data/lib/real_page/attribute_parser/decimal.rb +15 -0
  23. data/lib/real_page/attribute_parser/integer.rb +15 -0
  24. data/lib/real_page/attribute_parser/object.rb +13 -0
  25. data/lib/real_page/attribute_parser/string.rb +13 -0
  26. data/lib/real_page/document_parser.rb +6 -0
  27. data/lib/real_page/document_parser/base.rb +51 -0
  28. data/lib/real_page/document_parser/floor_plan_object.rb +30 -0
  29. data/lib/real_page/document_parser/guest_cards.rb +102 -0
  30. data/lib/real_page/document_parser/guest_cards/amenities.rb +34 -0
  31. data/lib/real_page/document_parser/guest_cards/prospects.rb +45 -0
  32. data/lib/real_page/document_parser/leases.rb +37 -0
  33. data/lib/real_page/document_parser/picklist.rb +38 -0
  34. data/lib/real_page/document_parser/rent_matrices.rb +39 -0
  35. data/lib/real_page/document_parser/rent_matrices/options.rb +31 -0
  36. data/lib/real_page/document_parser/rent_matrices/rows.rb +30 -0
  37. data/lib/real_page/document_parser/unit_object.rb +30 -0
  38. data/lib/real_page/error/bad_request.rb +18 -0
  39. data/lib/real_page/error/base.rb +9 -0
  40. data/lib/real_page/error/invalid_configuration.rb +9 -0
  41. data/lib/real_page/error/invalid_response.rb +9 -0
  42. data/lib/real_page/error/request_fault.rb +19 -0
  43. data/lib/real_page/error/request_fault/details.rb +17 -0
  44. data/lib/real_page/model/activity.rb +39 -0
  45. data/lib/real_page/model/address.rb +17 -0
  46. data/lib/real_page/model/amenity.rb +14 -0
  47. data/lib/real_page/model/appointment.rb +23 -0
  48. data/lib/real_page/model/base.rb +63 -0
  49. data/lib/real_page/model/base/attribute.rb +56 -0
  50. data/lib/real_page/model/base/attribute_store.rb +37 -0
  51. data/lib/real_page/model/floor_plan.rb +33 -0
  52. data/lib/real_page/model/follow_up.rb +34 -0
  53. data/lib/real_page/model/guest_card.rb +49 -0
  54. data/lib/real_page/model/lease.rb +36 -0
  55. data/lib/real_page/model/lease_action.rb +32 -0
  56. data/lib/real_page/model/phone_number.rb +13 -0
  57. data/lib/real_page/model/picklist_item.rb +10 -0
  58. data/lib/real_page/model/preferences.rb +25 -0
  59. data/lib/real_page/model/prospect.rb +35 -0
  60. data/lib/real_page/model/quote.rb +56 -0
  61. data/lib/real_page/model/rent_matrix.rb +16 -0
  62. data/lib/real_page/model/rent_matrix/concessions.rb +15 -0
  63. data/lib/real_page/model/rent_matrix/option.rb +19 -0
  64. data/lib/real_page/model/rent_matrix/row.rb +18 -0
  65. data/lib/real_page/model/screening.rb +22 -0
  66. data/lib/real_page/model/unit.rb +61 -0
  67. data/lib/real_page/model/unit_shown.rb +48 -0
  68. data/lib/real_page/parameter/list_criterion.rb +14 -0
  69. data/lib/real_page/request/base.rb +89 -0
  70. data/lib/real_page/request/get_floor_plan_list.rb +45 -0
  71. data/lib/real_page/request/get_leases_by_traffic_source.rb +59 -0
  72. data/lib/real_page/request/get_marketing_sources_by_property.rb +23 -0
  73. data/lib/real_page/request/get_rent_matrix.rb +57 -0
  74. data/lib/real_page/request/get_units_by_property.rb +39 -0
  75. data/lib/real_page/request/prospect_search.rb +50 -0
  76. data/lib/real_page/request_section.rb +6 -0
  77. data/lib/real_page/request_section/auth.rb +31 -0
  78. data/lib/real_page/request_section/get_rent_matrix.rb +32 -0
  79. data/lib/real_page/request_section/list_criteria.rb +29 -0
  80. data/lib/real_page/request_section/parameter.rb +31 -0
  81. data/lib/real_page/request_section/prospect_search_criterion.rb +24 -0
  82. data/lib/real_page/utils.rb +6 -0
  83. data/lib/real_page/utils/array_fetcher.rb +35 -0
  84. data/lib/real_page/utils/configuration_validator.rb +20 -0
  85. data/lib/real_page/utils/request_fetcher.rb +30 -0
  86. data/lib/real_page/utils/request_generator.rb +52 -0
  87. data/lib/real_page/utils/snowflake_event_tracker.rb +107 -0
  88. data/lib/real_page/validator.rb +6 -0
  89. data/lib/real_page/validator/move_in_report.rb +65 -0
  90. data/lib/real_page/validator/prospects_data.rb +93 -0
  91. data/lib/real_page/validator/request_errors.rb +97 -0
  92. data/lib/real_page/validator/request_fault.rb +97 -0
  93. data/lib/real_page/version.rb +3 -0
  94. data/real_page.gemspec +32 -0
  95. metadata +291 -0
@@ -0,0 +1,14 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # A container for an Amenity as represented by RealPage.
6
+ class Amenity < Base
7
+ string_attrs *%i[
8
+ id
9
+ pmc_id
10
+ site_id
11
+ ]
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,23 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a Appointment from a RealPage response.
6
+ class Appointment < Base
7
+ integer_attrs *%w[
8
+ day
9
+ hour
10
+ minute
11
+ month
12
+ year
13
+ ]
14
+
15
+ string_attrs *%i[
16
+ leasing_agent_id
17
+ pmc_id
18
+ site_id
19
+ task_notes
20
+ ]
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,63 @@
1
+ require 'real_page/attribute_parser'
2
+
3
+ require_relative 'base/attribute_store'
4
+
5
+ module RealPage
6
+ module Model
7
+ # Base class for models, which are the return values from Requests
8
+ class Base
9
+ class << self
10
+ attr_accessor :attribute_store
11
+ end
12
+
13
+ # Create a DSL to define the models attributes and their data types. This
14
+ # bit of meta-programming will create a class method for each data type
15
+ # to define the model's attributes of the type, e.g.
16
+ #
17
+ # class LostAndFound < Base
18
+ # date_attr :found_date, :lost_date
19
+ # end
20
+ #
21
+ # When a new LostAndFound is initialized (from a RealPage response hash,
22
+ # that may have the keys 'founddate' and 'lostdate'), it will create
23
+ # attribute readers for #found_date and #lost_date that return Date
24
+ # instances.
25
+ #
26
+ # Boolean attributes will have the existential '?', e.g.
27
+ #
28
+ # class LostAndFound < Base
29
+ # boolean_attr :found
30
+ # end
31
+ #
32
+ # lost_and_found = LostAndFound.new('foundbit' => '1')
33
+ # lost_and_found.found?
34
+ # # => true
35
+ %i[boolean date date_time decimal integer object string].each do |data_type|
36
+ define_singleton_method "#{data_type}_attrs" do |*attrs|
37
+ self.attribute_store ||= AttributeStore.new(self)
38
+ attribute_store.add(data_type, attrs).each do |attribute|
39
+ define_method attribute.accessor_name do
40
+ instance_variable_get("@#{attribute.name}")
41
+ end
42
+ end
43
+ end
44
+ end
45
+
46
+ # Initialize a new model with the response hash from RealPage. Attribute
47
+ # values are parsed into their configured data types.
48
+ #
49
+ # @param attrs [Hash<String, Object>] the response hash from RealPage.
50
+ # Attribute keys are case insensitive.
51
+ def initialize(attrs = {})
52
+ attrs.each do |attr, value|
53
+ attribute = self.class.attribute_store.find(attr)
54
+ next unless attribute
55
+ parser = AttributeParser.new(value: value, type: attribute.type)
56
+ instance_variable_set("@#{attribute.name}", parser.parse)
57
+ end
58
+ end
59
+ end
60
+
61
+ private_constant :Base
62
+ end
63
+ end
@@ -0,0 +1,56 @@
1
+ module RealPage
2
+ module Model
3
+ class Base
4
+ # Encapsulate a model attribute
5
+ class Attribute
6
+ attr_reader :prefix, :type, :name
7
+
8
+ def initialize(prefix:, type:, name:)
9
+ @prefix = prefix
10
+ @type = type
11
+ @name = name.to_s
12
+ end
13
+
14
+ # @return [String] the name of the method on the model used to access
15
+ # this attribute
16
+ def accessor_name
17
+ type == :boolean ? "#{name}?" : name
18
+ end
19
+
20
+ # There is some magic happening here to support more convenient
21
+ # attribute names. Since Model::Base.new can take parameters from a
22
+ # parsed XML document or from a human, we need to be able to look up
23
+ # the attribute based on either. The general mapping looks like:
24
+ #
25
+ # XML node | attribute name
26
+ # ---------------+--------------------
27
+ # SomeThing | some_thing
28
+ # something | some_thing
29
+ # foobarid | bar_id (if in Model::Foo)
30
+ # somethingbit | some_thing (if defined as a :boolean)
31
+ # somethingflag | some_thing (if defined as a :boolean)
32
+ #
33
+ # @param attr [String|Symbol] the name of the attribute or the XML node
34
+ # name from the RealPage response, e.g. :made_ready_date or
35
+ # "MadeReadyDate"
36
+ # @return [true|false] true iff the value passed in is for this
37
+ # Attribute
38
+ def matches?(attr)
39
+ possible_names.include?(attr.to_s.downcase)
40
+ end
41
+
42
+ private
43
+
44
+ def possible_names
45
+ squished_name = name.gsub(/_/, '')
46
+ prefixed_name = "#{prefix}#{squished_name}"
47
+ names = [name, squished_name, prefixed_name]
48
+ if type == :boolean
49
+ names.concat(["#{squished_name}flag", "#{squished_name}bit"])
50
+ end
51
+ names
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,37 @@
1
+ require_relative 'attribute'
2
+
3
+ module RealPage
4
+ module Model
5
+ class Base
6
+ # Hold attributes defined with the DSL in Models
7
+ class AttributeStore
8
+ def initialize(model_class)
9
+ @model_class = model_class
10
+ @attributes = []
11
+ end
12
+
13
+ # Add all attributes of the same type to the AttributeStore
14
+ def add(type, attrs)
15
+ attrs.map do |attr|
16
+ attribute = Attribute.new(prefix: prefix, type: type, name: attr)
17
+ @attributes << attribute
18
+ attribute
19
+ end
20
+ end
21
+
22
+ # Find a specific attribute with the given name
23
+ def find(attr)
24
+ attributes.detect { |attribute| attribute.matches?(attr) }
25
+ end
26
+
27
+ private
28
+
29
+ attr_reader :attributes, :model_class
30
+
31
+ def prefix
32
+ model_class.name.split('::').last.downcase
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,33 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # A container for a floor plan as represented by RealPage.
6
+ class FloorPlan < Base
7
+ boolean_attrs *%i[excluded_from_occupancy]
8
+
9
+ decimal_attrs *%i[
10
+ bathrooms
11
+ rent_max
12
+ rent_min
13
+ ]
14
+
15
+ integer_attrs *%i[
16
+ bedrooms
17
+ gross_square_footage
18
+ id
19
+ maximum_occupants
20
+ rentable_square_footage
21
+ ]
22
+
23
+ string_attrs *%i[
24
+ code
25
+ description
26
+ group_id
27
+ group_name
28
+ name
29
+ name_marketing
30
+ ]
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,34 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a FollowUp from a RealPage response.
6
+ class FollowUp < Base
7
+ boolean_attrs *%i[
8
+ past_due_task
9
+ ]
10
+
11
+ date_attrs *%i[
12
+ task_contact_date_time
13
+ ]
14
+
15
+ integer_attrs *%i[
16
+ agent_id
17
+ task_id
18
+ ]
19
+
20
+ string_attrs *%i[
21
+ agent_name
22
+ notes
23
+ priority_cd
24
+ task
25
+ task_appt_date_time
26
+ task_category_cd
27
+ task_confirmed
28
+ task_contact_type_cd
29
+ task_duration_end
30
+ task_duration_start
31
+ ]
32
+ end
33
+ end
34
+ end
@@ -0,0 +1,49 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # A container for a guest_card as represented by RealPage.
6
+ class GuestCard < Base
7
+ boolean_attrs *%i[
8
+ status_is_active
9
+ status_is_leased
10
+ status_is_lost
11
+ ]
12
+
13
+ date_attrs *%i[desired_lease_end_date]
14
+
15
+ date_time_attrs *%i[create_date]
16
+
17
+ object_attrs *%i[
18
+ activities
19
+ amenities
20
+ appointment
21
+ follow_ups
22
+ lease_actions
23
+ preferences
24
+ prospects
25
+ quotes
26
+ screenings
27
+ units_shown
28
+ ]
29
+
30
+ string_attrs *%i[
31
+ contact_type
32
+ customer_id
33
+ date_contact
34
+ date_followup
35
+ id
36
+ leasing_agent_id
37
+ move_in_reason
38
+ pet_weight_range
39
+ pmc_id
40
+ primary_lead_source
41
+ primary_traffic_source_minor
42
+ property_status
43
+ prospect_comment
44
+ secondary_lead_source
45
+ site_id
46
+ ]
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,36 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # A container for a lease as represented by RealPage.
6
+ class Lease < Base
7
+ date_attrs *%i[begin_date end_date move_in_date]
8
+
9
+ string_attrs *%i[
10
+ email
11
+ first_name
12
+ guest_card_id
13
+ id
14
+ last_name
15
+ middle_name
16
+ resident_household_id
17
+ resident_member_id
18
+ phone_1
19
+ phone_2
20
+ phone_ext_1
21
+ phone_ext_2
22
+ term_id
23
+ type
24
+ unit_id
25
+ unit_number
26
+ ]
27
+
28
+ # Possible values for leasetype, provided as a convenience
29
+ module Type
30
+ FIRST_LEASE = 'First Lease'.freeze
31
+ RENEWAL = 'Renewal'.freeze
32
+ TRANSFER = 'Transfer'.freeze
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,32 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a LeaseAction from a RealPage response.
6
+ class LeaseAction < Base
7
+ boolean_attrs *%i[
8
+ editable
9
+ rentable_item_reserved
10
+ ]
11
+
12
+ date_attrs *%i[
13
+ note_date
14
+ sort_date
15
+ ]
16
+
17
+ integer_attrs *%i[
18
+ lal_org_lea_id
19
+ note_comment_length
20
+ note_id
21
+ ]
22
+
23
+ string_attrs *%i[
24
+ for_correct_date_sort
25
+ note_comment
26
+ note_source
27
+ note_type
28
+ note_user
29
+ ]
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,13 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a PhoneNumber from a RealPage response.
6
+ class PhoneNumber < Base
7
+ string_attrs *%i[
8
+ type
9
+ number
10
+ ]
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,10 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a PicklistItem from a RealPage response.
6
+ class PicklistItem < Base
7
+ string_attrs *%i[value text]
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,25 @@
1
+ require_relative 'base'
2
+
3
+ module RealPage
4
+ module Model
5
+ # Object to encapsulate a Preferences from a RealPage response.
6
+ class Preferences < Base
7
+ date_attrs *%i[
8
+ date_needed
9
+ ]
10
+
11
+ integer_attrs *%i[
12
+ desired_rent
13
+ floorplan_id
14
+ lease_term_months
15
+ ]
16
+
17
+ string_attrs *%i[
18
+ floorplan_group_id
19
+ occupants
20
+ price_range_id
21
+ site_id
22
+ ]
23
+ end
24
+ end
25
+ end