yardi 4.0.8
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.circleci/config.yml +29 -0
- data/.gitignore +5 -0
- data/.rspec +3 -0
- data/.rubocop.yml +20 -0
- data/CODEOWNERS +1 -0
- data/CODE_OF_CONDUCT.md +13 -0
- data/Gemfile +4 -0
- data/README.md +212 -0
- data/Rakefile +7 -0
- data/bin/console +15 -0
- data/config/multi_xml.rb +4 -0
- data/docs/contributing.md +24 -0
- data/docs/getting_started.md +14 -0
- data/lib/yardi.rb +54 -0
- data/lib/yardi/document_parser.rb +6 -0
- data/lib/yardi/document_parser/base.rb +85 -0
- data/lib/yardi/document_parser/guest_card_import_response_object.rb +72 -0
- data/lib/yardi/document_parser/prospects.rb +79 -0
- data/lib/yardi/document_parser/residents.rb +59 -0
- data/lib/yardi/error/base.rb +7 -0
- data/lib/yardi/error/connection_error.rb +12 -0
- data/lib/yardi/error/empty_response.rb +11 -0
- data/lib/yardi/error/error_response.rb +11 -0
- data/lib/yardi/error/fault_response.rb +14 -0
- data/lib/yardi/error/guests_not_found.rb +10 -0
- data/lib/yardi/error/invalid_configuration.rb +11 -0
- data/lib/yardi/error/missing_property.rb +10 -0
- data/lib/yardi/error/no_results.rb +10 -0
- data/lib/yardi/error/resource_not_found.rb +9 -0
- data/lib/yardi/error/service_unavailable.rb +11 -0
- data/lib/yardi/error/unparsable_response.rb +11 -0
- data/lib/yardi/model/event.rb +18 -0
- data/lib/yardi/model/guest_card_response.rb +12 -0
- data/lib/yardi/model/prospect.rb +49 -0
- data/lib/yardi/model/resident.rb +36 -0
- data/lib/yardi/parameter/agent.rb +13 -0
- data/lib/yardi/parameter/contact_info.rb +13 -0
- data/lib/yardi/parameter/credential.rb +16 -0
- data/lib/yardi/parameter/property.rb +35 -0
- data/lib/yardi/parameter/prospect.rb +25 -0
- data/lib/yardi/parameter/user.rb +64 -0
- data/lib/yardi/request/base.rb +99 -0
- data/lib/yardi/request/get_residents.rb +39 -0
- data/lib/yardi/request/get_yardi_guest_activity.rb +85 -0
- data/lib/yardi/request/import_yardi_guest.rb +73 -0
- data/lib/yardi/request_section.rb +24 -0
- data/lib/yardi/request_section/authentication.rb +24 -0
- data/lib/yardi/request_section/lead_management.rb +148 -0
- data/lib/yardi/request_section/prospect.rb +27 -0
- data/lib/yardi/request_section/residents.rb +18 -0
- data/lib/yardi/utils.rb +6 -0
- data/lib/yardi/utils/configuration_validator.rb +17 -0
- data/lib/yardi/utils/phone_parser.rb +23 -0
- data/lib/yardi/utils/request_fetcher.rb +47 -0
- data/lib/yardi/utils/request_generator.rb +88 -0
- data/lib/yardi/validator.rb +6 -0
- data/lib/yardi/validator/empty_response.rb +43 -0
- data/lib/yardi/validator/error_response.rb +87 -0
- data/lib/yardi/validator/fault_response.rb +40 -0
- data/lib/yardi/validator/missing_property.rb +60 -0
- data/lib/yardi/version.rb +5 -0
- data/yardi.gemspec +31 -0
- metadata +246 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 23da65dd97a13b80552415335b257aad1f1ae7f8
|
4
|
+
data.tar.gz: 75a31101f34ac6e8d129cc97aeb82b0f05710c86
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: a8ee7e3f3e4edeb6a33dea96055ae771e197870df3df603e9ca90145faa10afa7497725b8fb4884d5e39b2bf61bcb79575ef3162f677990e58209e23db59aae8
|
7
|
+
data.tar.gz: b1f9f8ebde63520dcf5242153dcc37f939e63e2faa3d7b4950ac7147a70e195f54873804ed190291d427212599dc3499567dd7f5d9e0540ea64344854c693529
|
@@ -0,0 +1,29 @@
|
|
1
|
+
version: 2.1
|
2
|
+
|
3
|
+
jobs:
|
4
|
+
test:
|
5
|
+
docker:
|
6
|
+
- image: circleci/ruby:2.4.5
|
7
|
+
environment:
|
8
|
+
PG_USER: circleci
|
9
|
+
|
10
|
+
working_directory: ~/yardi
|
11
|
+
|
12
|
+
steps:
|
13
|
+
- checkout
|
14
|
+
- restore_cache:
|
15
|
+
key: dependency-cache-{{ checksum "Gemfile" }}
|
16
|
+
- run:
|
17
|
+
command: bundle install
|
18
|
+
- run:
|
19
|
+
command: bundle exec rake
|
20
|
+
- save_cache:
|
21
|
+
key: dependency-cache-{{ checksum "Gemfile" }}
|
22
|
+
paths:
|
23
|
+
- /usr/local/bundle/cache
|
24
|
+
|
25
|
+
workflows:
|
26
|
+
version: 2.1
|
27
|
+
testing:
|
28
|
+
jobs:
|
29
|
+
- test
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
AllCops:
|
2
|
+
TargetRubyVersion: 2.3
|
3
|
+
|
4
|
+
Style/MultilineMethodCallIndentation:
|
5
|
+
EnforcedStyle: indented
|
6
|
+
|
7
|
+
Style/NumericLiterals:
|
8
|
+
Enabled: false
|
9
|
+
|
10
|
+
Style/FrozenStringLiteralComment:
|
11
|
+
Enabled: false
|
12
|
+
|
13
|
+
# We prefer [] over () for % delimited Arrays such as %w and %i.
|
14
|
+
PercentLiteralDelimiters:
|
15
|
+
PreferredDelimiters:
|
16
|
+
'%i': '[]'
|
17
|
+
'%w': '[]'
|
18
|
+
|
19
|
+
Performance/Casecmp:
|
20
|
+
Enabled: false
|
data/CODEOWNERS
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
* @heidi
|
data/CODE_OF_CONDUCT.md
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
# Contributor Code of Conduct
|
2
|
+
|
3
|
+
As contributors and maintainers of this project, we pledge to respect all people who contribute through reporting issues, posting feature requests, updating documentation, submitting pull requests or patches, and other activities.
|
4
|
+
|
5
|
+
We are committed to making participation in this project a harassment-free experience for everyone, regardless of level of experience, gender, gender identity and expression, sexual orientation, disability, personal appearance, body size, race, age, or religion.
|
6
|
+
|
7
|
+
Examples of unacceptable behavior by participants include the use of sexual language or imagery, derogatory comments or personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
8
|
+
|
9
|
+
Project maintainers have the right and responsibility to remove, edit, or reject comments, commits, code, wiki edits, issues, and other contributions that are not aligned to this Code of Conduct. Project maintainers who do not follow the Code of Conduct may be removed from the project team.
|
10
|
+
|
11
|
+
Instances of abusive, harassing, or otherwise unacceptable behavior may be reported by opening an issue or contacting one or more of the project maintainers.
|
12
|
+
|
13
|
+
This Code of Conduct is adapted from the [Contributor Covenant](http:contributor-covenant.org), version 1.0.0, available at [http://contributor-covenant.org/version/1/0/0/](http://contributor-covenant.org/version/1/0/0/)
|
data/Gemfile
ADDED
data/README.md
ADDED
@@ -0,0 +1,212 @@
|
|
1
|
+
[![CircleCI](https://circleci.com/gh/apartmentlist/yardi.svg?style=svg&circle-token=f257321b5c0e4a15a49eda74aa869a09d6db2f19)](https://circleci.com/gh/apartmentlist/yardi)
|
2
|
+
|
3
|
+
# yardi
|
4
|
+
A Ruby client for v4 of Yardi's Guestcard (and soon ILS) API
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
```ruby
|
11
|
+
gem 'yardi'
|
12
|
+
```
|
13
|
+
|
14
|
+
And then re-install your application's bundle:
|
15
|
+
|
16
|
+
$ bundle install
|
17
|
+
|
18
|
+
Or install it yourself as:
|
19
|
+
|
20
|
+
$ gem install yardi
|
21
|
+
|
22
|
+
## Usage
|
23
|
+
|
24
|
+
### Configuration
|
25
|
+
|
26
|
+
Configure the gem with your Yardi license, entity and platform:
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
Yardi.configure do |config|
|
30
|
+
# Use your web service URL below
|
31
|
+
config.license_key = ENV['LICENSE_KEY']
|
32
|
+
config.entity = 'Apartment List'
|
33
|
+
config.platform = 'SQL Server'
|
34
|
+
end
|
35
|
+
```
|
36
|
+
|
37
|
+
### Useful classes
|
38
|
+
|
39
|
+
#### Yardi::Credential
|
40
|
+
|
41
|
+
Yardi SOAP actions require authentication so the SOAP action classes
|
42
|
+
(see below) require a `:credential` parameter in the initializer.
|
43
|
+
|
44
|
+
```ruby
|
45
|
+
credential = Yardi::Credential.new(
|
46
|
+
username: 'my-username',
|
47
|
+
password: 'my-password',
|
48
|
+
database: 'test_db_live',
|
49
|
+
server: '0SQL_DBtest'
|
50
|
+
)
|
51
|
+
|
52
|
+
params = {
|
53
|
+
agent: Agent.new(first_name: 'Test', last_name: 'Agent'),
|
54
|
+
credential: credential,
|
55
|
+
... # any other required params
|
56
|
+
}
|
57
|
+
response = Yardi::Request::SomeSoapAction.new(params).perform
|
58
|
+
```
|
59
|
+
|
60
|
+
### SOAP Actions
|
61
|
+
|
62
|
+
To request an action, instantiate the appropriate class (see below) and invoke
|
63
|
+
`#perform` on it. The API response will be parsed and returned as a ruby object.
|
64
|
+
|
65
|
+
#### Yardi::Action::ImportYardiGuest_Login
|
66
|
+
Insert a guest card into Yardi's system.
|
67
|
+
|
68
|
+
##### Initialization parameters
|
69
|
+
|
70
|
+
* `agent [Yardi::Parameter::Agent]`
|
71
|
+
* `credential [Yardi::Parameter::Credential]`
|
72
|
+
information needed to authenticate with Yardi
|
73
|
+
* `lead_source [String]` what Yardi calls TransactionSource
|
74
|
+
* `reason [String]` what Yardi calls Event Reasons. This is the reason for
|
75
|
+
the event, e.g. price inquiry, tour, etc.
|
76
|
+
* `property [Yardi::Parameter::Property]` the property to associate the guest
|
77
|
+
card with
|
78
|
+
* `user [Yardi::Parameter::User]` the user to associate the guest card with
|
79
|
+
|
80
|
+
#### Yardi::Request::GetResidents
|
81
|
+
Get all the residents for a given property ID.
|
82
|
+
|
83
|
+
##### Initialization parameters
|
84
|
+
|
85
|
+
* `credential [Yardi::Parameter::Credential]` information needed to authenticate with Yardi
|
86
|
+
* `property_id [String]` the remote `YardiPropertyId`
|
87
|
+
|
88
|
+
##### Response
|
89
|
+
An array of `Yardi::Model::Resident`s
|
90
|
+
|
91
|
+
###### Example
|
92
|
+
```ruby
|
93
|
+
Yardi::Request::GetResidents.new(
|
94
|
+
credential: credential, params: { property_id: 'p263656'}
|
95
|
+
).perform
|
96
|
+
|
97
|
+
=>
|
98
|
+
|
99
|
+
[
|
100
|
+
#<Yardi::Model::Resident:0x007fe922f01d98
|
101
|
+
@email="jb007@mi6.uk",
|
102
|
+
@first_name="James",
|
103
|
+
@last_name="Bond",
|
104
|
+
@lease_id="sprng007",
|
105
|
+
@lease_lead_id="p0012007",
|
106
|
+
@move_in_date="12/23/2014",
|
107
|
+
@phones=[
|
108
|
+
{
|
109
|
+
"PhoneType" => "home",
|
110
|
+
"PhoneDescription" => "Home",
|
111
|
+
"PhoneNumber" => "(123) 456-7890"
|
112
|
+
}
|
113
|
+
],
|
114
|
+
@status="Current",
|
115
|
+
@unit_name="A2"
|
116
|
+
>,
|
117
|
+
#<Yardi::Model::Resident:0x007fe922f01d48
|
118
|
+
@email="itsjasonbourne@cia.gov",
|
119
|
+
@first_name="Jason",
|
120
|
+
@last_name="Bourne",
|
121
|
+
@lease_id="sprng456",
|
122
|
+
@lease_lead_id="p0041571",
|
123
|
+
@move_in_date="10/13/2016",
|
124
|
+
@phones=[
|
125
|
+
{
|
126
|
+
"PhoneType" => "cell",
|
127
|
+
"PhoneDescription" => "Mobile",
|
128
|
+
"PhoneNumber" => "8507742326"
|
129
|
+
}
|
130
|
+
],
|
131
|
+
@status="Current",
|
132
|
+
@unit_name="A3"
|
133
|
+
>
|
134
|
+
]
|
135
|
+
```
|
136
|
+
|
137
|
+
#### Yardi::Request::GetYardiGuestActivity
|
138
|
+
|
139
|
+
Get a list of `Yardi::Model::Prospect`s for a given Prospect at the specified property ID.
|
140
|
+
|
141
|
+
##### Initialization parameters
|
142
|
+
|
143
|
+
* `credential [Yardi::Parameter::Credential]` information needed to authenticate with Yardi
|
144
|
+
* `params [Hash]`
|
145
|
+
* `property_id [String]`
|
146
|
+
* `prospect [Yardi::Parameter::Prospect]`
|
147
|
+
|
148
|
+
##### Response
|
149
|
+
|
150
|
+
An array of `Yardi::Model::Prospect`s
|
151
|
+
|
152
|
+
###### Example
|
153
|
+
```ruby
|
154
|
+
Yardi::Request::GetYardiGuestActivity.new(
|
155
|
+
credential: credential,
|
156
|
+
params: { property_id: 'p263656', prospect: prospect }
|
157
|
+
).perform
|
158
|
+
# => [#<Yardi::Model::Prospect>, #<Yardi::Model::Prospect>]
|
159
|
+
```
|
160
|
+
|
161
|
+
#### Yardi::Model::Prospect
|
162
|
+
|
163
|
+
##### Attributes
|
164
|
+
|
165
|
+
* `first_name` The `Prospect`'s first name according to Yardi's database
|
166
|
+
* `last_name` The `Prospect`'s last name according to Yardi's database
|
167
|
+
* `email` The `Prospect`'s email address according to Yardi's database
|
168
|
+
* `phones` An Array of the `Prospect`'s phone numbers, or `nil` if there are none
|
169
|
+
* `events` An Array of `Yardi::Model::Event` objects
|
170
|
+
* `prospect_id` The `Prospect` id from Yardi's database e.g. `"p00003693"`
|
171
|
+
* `tenant_id` The tenant id from Yardi's database e.g. `"t000456"`
|
172
|
+
|
173
|
+
## Development
|
174
|
+
|
175
|
+
To install this gem onto your local machine, run `bundle exec rake install`.
|
176
|
+
To release a new version, update the version number in `version.rb`, and then
|
177
|
+
run `bundle exec rake release` to create a git tag for the version, push git
|
178
|
+
commits and tags, and push the `.gem` file to
|
179
|
+
[rubygems.org](https://rubygems.org).
|
180
|
+
|
181
|
+
## Contributing
|
182
|
+
|
183
|
+
If you are interested in contributing to this project, please review the
|
184
|
+
[contribution guidelines](docs/contributing.md).
|
185
|
+
|
186
|
+
## Versions
|
187
|
+
- 4.0.0 Add handling for 404 errors and move ConnectionError to be a subclass of
|
188
|
+
Yardi::Error::Base
|
189
|
+
- 3.1.2 Fix Prospect parsing to properly handle missing `Event` nodes
|
190
|
+
- 3.1.1 Fix roommate parsing to properly extract roommate data from GetResidents response
|
191
|
+
- 3.1.0 Add roommates to Resident Model and Parser
|
192
|
+
- 3.0.6 Handle Yardi connection errors
|
193
|
+
- 3.0.5 Handle missing event ids
|
194
|
+
- 3.0.4 Add GuestsNotFound Error
|
195
|
+
- 3.0.3 Handle roommates in prospect search results
|
196
|
+
- 3.0.2 Raise an error when GetResidents call returns no Residents
|
197
|
+
- 3.0.1 Handle parsing resident response when there is only one result
|
198
|
+
- 3.0.0 GetYardiGuestActivity returns an Array of Prospects
|
199
|
+
- 2.0.0 GetYardiGuestActivity uses a Prospect parameter
|
200
|
+
- 1.0.3 Fix when GetResidents call returns nil dates
|
201
|
+
- 1.0.2 Fix when GetResidents call returns a single phone number
|
202
|
+
- 1.0.1 Fix when GetResidents call returns nil phone numbers
|
203
|
+
- 1.0.0 Change response for GetYardiGuestActivity to be an array of Events instead of Tours. Also add lease dates GetResidents response.
|
204
|
+
- 0.3.0 Add GetResidents request
|
205
|
+
- 0.2.1 Handle when Yardi's response is completely empty
|
206
|
+
- 0.2.0 Insert FirstContact events as Email instead of Other
|
207
|
+
- 0.1.5 Handle missing bed/price preferences
|
208
|
+
- 0.1.4 Fix Prospect search, which requires a property ID
|
209
|
+
- 0.1.3 Fetch existing tours from Yardi
|
210
|
+
- 0.1.2 Support custom connections for use with a proxy
|
211
|
+
- 0.1.1 Handle multiple errors in the response
|
212
|
+
- 0.1.0 Initial release with guestcard insertion and response handling
|
data/Rakefile
ADDED
data/bin/console
ADDED
@@ -0,0 +1,15 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
require 'bundler/setup'
|
4
|
+
require 'pry'
|
5
|
+
require 'yardi'
|
6
|
+
|
7
|
+
# You can add fixtures and/or initialization code here to make experimenting
|
8
|
+
# with your gem easier. You can also use a different console, if you like.
|
9
|
+
|
10
|
+
# (If you use this, don't forget to add pry to your Gemfile!)
|
11
|
+
# require "pry"
|
12
|
+
# Pry.start
|
13
|
+
|
14
|
+
require 'irb'
|
15
|
+
IRB.start
|
data/config/multi_xml.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
## Contributing
|
2
|
+
|
3
|
+
We happily accept issues and pull requests on GitHub.
|
4
|
+
|
5
|
+
Please review the design goals of this project and run the test suite before
|
6
|
+
submitting a pull request.
|
7
|
+
|
8
|
+
### Design goals
|
9
|
+
|
10
|
+
* Only test and document the public interfaces of this gem.
|
11
|
+
* When in doubt, please adhere to RuboCop's community style guide.
|
12
|
+
|
13
|
+
### Running tests
|
14
|
+
|
15
|
+
$ bundle exec rake
|
16
|
+
|
17
|
+
### Submitting a pull request
|
18
|
+
|
19
|
+
1. Fork it ( https://github.com/[my-github-username]/yardi/fork )
|
20
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
21
|
+
3. Run the test suite
|
22
|
+
4. Commit your changes (`git commit -am 'Add some feature'`)
|
23
|
+
5. Push to the branch (`git push origin my-new-feature`)
|
24
|
+
6. Create a new Pull Request
|
@@ -0,0 +1,14 @@
|
|
1
|
+
## Getting started
|
2
|
+
|
3
|
+
For developers interested in working on this gem please follow the
|
4
|
+
development setup instructions and the read over the
|
5
|
+
[contribution guidelines](contributing.md).
|
6
|
+
|
7
|
+
### Development setup
|
8
|
+
|
9
|
+
* Clone the repo
|
10
|
+
* Run `bundle install`
|
11
|
+
|
12
|
+
### Contributing
|
13
|
+
|
14
|
+
Please continue on to [the contributing documentation](contributing.md).
|
data/lib/yardi.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require_relative '../config/multi_xml.rb'
|
2
|
+
|
3
|
+
require 'yardi/error/base'
|
4
|
+
require 'yardi/error/connection_error'
|
5
|
+
require 'yardi/error/empty_response'
|
6
|
+
require 'yardi/error/error_response'
|
7
|
+
require 'yardi/error/fault_response'
|
8
|
+
require 'yardi/error/guests_not_found'
|
9
|
+
require 'yardi/error/invalid_configuration'
|
10
|
+
require 'yardi/error/missing_property'
|
11
|
+
require 'yardi/error/no_results'
|
12
|
+
require 'yardi/error/resource_not_found'
|
13
|
+
require 'yardi/error/service_unavailable'
|
14
|
+
require 'yardi/error/unparsable_response'
|
15
|
+
|
16
|
+
require 'yardi/model/event'
|
17
|
+
require 'yardi/model/guest_card_response'
|
18
|
+
require 'yardi/model/resident'
|
19
|
+
|
20
|
+
require 'yardi/parameter/agent'
|
21
|
+
require 'yardi/parameter/contact_info'
|
22
|
+
require 'yardi/parameter/credential'
|
23
|
+
require 'yardi/parameter/property'
|
24
|
+
require 'yardi/parameter/prospect'
|
25
|
+
require 'yardi/parameter/user'
|
26
|
+
|
27
|
+
require 'yardi/request/import_yardi_guest'
|
28
|
+
require 'yardi/request/get_yardi_guest_activity'
|
29
|
+
require 'yardi/request/get_residents'
|
30
|
+
|
31
|
+
require 'yardi/version'
|
32
|
+
# The toplevel Yardi module. This includes configuration information that
|
33
|
+
# we'll need to build requests. This information is the same for all of our
|
34
|
+
# clients. Client-specific configuration is specified in credential.rb.
|
35
|
+
module Yardi
|
36
|
+
CONFIG_KEYS = %i[
|
37
|
+
entity
|
38
|
+
license_key
|
39
|
+
platform
|
40
|
+
].freeze
|
41
|
+
|
42
|
+
Config = Struct.new(*CONFIG_KEYS)
|
43
|
+
private_constant :Config
|
44
|
+
|
45
|
+
class << self
|
46
|
+
def configure(&block)
|
47
|
+
yield config
|
48
|
+
end
|
49
|
+
|
50
|
+
def config
|
51
|
+
@config ||= Config.new
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'multi_xml'
|
2
|
+
|
3
|
+
require 'yardi/validator/error_response'
|
4
|
+
require 'yardi/validator/empty_response'
|
5
|
+
require 'yardi/validator/missing_property'
|
6
|
+
require 'yardi/validator/fault_response'
|
7
|
+
|
8
|
+
require 'yardi/document_parser'
|
9
|
+
|
10
|
+
module Yardi
|
11
|
+
module DocumentParser
|
12
|
+
# Base class for parsing Yardi responses. Subclasses must implement
|
13
|
+
# #parse_body and can optionally override #validator_classes to add more
|
14
|
+
# validation than just the default
|
15
|
+
class Base
|
16
|
+
# Order matters here. The parsing logic for an ErrorResponse relies on the
|
17
|
+
# fact that the response is not empty. The MissingProperty error looks
|
18
|
+
# similar to the unknown error response, so we want to check that first
|
19
|
+
# in order to raise a configuration error if we can.
|
20
|
+
DEFAULT_VALIDATOR_CLASSES = [
|
21
|
+
Validator::EmptyResponse,
|
22
|
+
Validator::MissingProperty,
|
23
|
+
Validator::ErrorResponse,
|
24
|
+
Validator::FaultResponse
|
25
|
+
].freeze
|
26
|
+
private_constant :DEFAULT_VALIDATOR_CLASSES
|
27
|
+
|
28
|
+
# @param xml [String] the XML response from the request
|
29
|
+
# @return [Object] the parsed object(s) from the rsesponse
|
30
|
+
# @raise [Yardi::Error::Base] if the response is invalid
|
31
|
+
def parse(xml)
|
32
|
+
begin
|
33
|
+
parsed = MultiXml.parse(xml)
|
34
|
+
rescue MultiXml::ParseError => e
|
35
|
+
raise unparsable_xml_error(xml)
|
36
|
+
end
|
37
|
+
|
38
|
+
# This is a temporary code to be able to see what Yardi response
|
39
|
+
# looks like when envelope is empty.
|
40
|
+
if !parsed.empty? && parsed['soap:Envelope'].nil?
|
41
|
+
raise Yardi::Error::UnparsableResponse.new(xml)
|
42
|
+
end
|
43
|
+
|
44
|
+
[*DEFAULT_VALIDATOR_CLASSES, *validator_classes].each do |klass|
|
45
|
+
klass.new(action: action, parsed_response: parsed).validate!
|
46
|
+
end
|
47
|
+
|
48
|
+
parse_body(parsed['soap:Envelope']['soap:Body'])
|
49
|
+
end
|
50
|
+
|
51
|
+
private
|
52
|
+
|
53
|
+
def result_node
|
54
|
+
body["#{action}Response"]["#{action}Result"]
|
55
|
+
end
|
56
|
+
|
57
|
+
# @param body [Hash<String, Object>] the body of the XML response parsed
|
58
|
+
# into a Hash
|
59
|
+
# @return [Object] the parsed object(s) from the rsesponse
|
60
|
+
# @raise [Yardi::Error::Base] if the response is invalid
|
61
|
+
def parse_body(body)
|
62
|
+
raise NotImplementedError,
|
63
|
+
"#{self.class.name} must implement #{__method__}"
|
64
|
+
end
|
65
|
+
|
66
|
+
def action
|
67
|
+
self.class::SOAP_ACTION
|
68
|
+
end
|
69
|
+
|
70
|
+
def validator_classes
|
71
|
+
[]
|
72
|
+
end
|
73
|
+
|
74
|
+
def unparsable_xml_error(response)
|
75
|
+
if !response.nil? && response =~ /Service Unavailable/
|
76
|
+
Yardi::Error::ServiceUnavailable.new(response)
|
77
|
+
elsif !response.nil? && response =~ /!DOCTYPE html/
|
78
|
+
Yardi::Error::ErrorResponse.new(response)
|
79
|
+
else
|
80
|
+
Yardi::Error::UnparsableResponse.new(response)
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|