allhomes_xml 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ # Require all other files
2
+ Dir[File.dirname(__FILE__) + '/allhomes_xml/*.rb'].each {|file| require file }
3
+ # Require price files
4
+ Dir[File.dirname(__FILE__) + '/allhomes_xml/price/*.rb'].each {|file| require file }
@@ -0,0 +1,17 @@
1
+ module AllhomesXml
2
+
3
+ # Storage container for agents - primary and secondary(optional)
4
+ class Agents
5
+
6
+ attr_accessor :primary_agent, :secondary_agent
7
+
8
+ def primary hash
9
+ self.primary_agent = hash
10
+ end
11
+ def secondary hash
12
+ self.secondary_agent = hash
13
+ end
14
+
15
+ end
16
+
17
+ end
File without changes
@@ -0,0 +1,7 @@
1
+ module AllhomesXml
2
+
3
+ # Storage container for attributes
4
+ class Attributes < Hash
5
+ end
6
+
7
+ end
@@ -0,0 +1,31 @@
1
+ module AllhomesXml
2
+
3
+ # Creates a template listing for use by higher level classes
4
+ class BasicListing
5
+
6
+ # All generic attributes common to all listings
7
+ attr_accessor :id, :property_type, :agency_id, :agents, :unit_number, :street_number, :street_name, :street_type, :complex, :suburb, :postcode, :state, :country, :hide_address, :title, :description, :eer, :photos, :price, :exhibitions, :bedrooms, :bathrooms, :ensuites, :carspaces, :garagespaces, :attributes
8
+
9
+ def required
10
+ [:id, :agents, :suburb, :property_type, :postcode]
11
+ end
12
+
13
+ # Creates a new basic listing - takes a hash full of attributes as an argument
14
+ def initialize(args)
15
+
16
+ args.each_pair do |attribute, value|
17
+
18
+ # Remove junk off the beginning/end of strings
19
+ value.strip! if value.instance_of? String and not attribute == :description
20
+
21
+ send "#{attribute}=", value
22
+
23
+ end
24
+
25
+ required.each { |field| raise "#{field} field cannot be blank - property #{id}!" if self.send(field).blank? }
26
+
27
+ end
28
+
29
+ end
30
+
31
+ end
@@ -0,0 +1,15 @@
1
+ module AllhomesXml
2
+
3
+ module Price
4
+
5
+ class BasicPrice
6
+ def initialize(args)
7
+ args.each_pair do |attribute, value|
8
+ send "#{attribute}=", value
9
+ end
10
+ end
11
+ end
12
+
13
+ end
14
+
15
+ end
@@ -0,0 +1,7 @@
1
+ module AllhomesXml
2
+
3
+ # Storage container for exhibitions
4
+ class AllhomesXml::Exhibitions < Array
5
+ end
6
+
7
+ end
@@ -0,0 +1,416 @@
1
+ module AllhomesXml
2
+
3
+ class Generator
4
+
5
+ COMMERCIAL_PROPERTY_TYPES = %w(office hotel industrial motel retail warehouse)
6
+
7
+ # Creates a new XML class to house all data
8
+ # Takes an Allhomes username and password hash as it's argument
9
+ def initialize(args)
10
+
11
+ @username = args[:username]
12
+ @password = args[:password]
13
+ @properties = []
14
+
15
+ end
16
+
17
+ def << property
18
+ @properties << property
19
+ end
20
+
21
+ # Generates the XML
22
+ def generate
23
+
24
+ require 'builder'
25
+
26
+ xml = Builder::XmlMarkup.new :indent => 4
27
+
28
+ xml.instruct! :xml, :version => "1.0"
29
+
30
+ time = Time.now
31
+ xml.listings({:feedId => time.to_i,
32
+ :generated => time.xmlschema,
33
+ :username => @username,
34
+ :password => @password,
35
+ :xmlns => "http://www.allhomes.com.au/2008/v1/listingFeed",
36
+ :'xmlns:xsi' => "http://www.w3.org/2001/XMLSchema-instance",
37
+ :'xsi:schemaLocation' => "http://www.allhomes.com.au/2008/v1/listingFeed listingFeed.xsd "}) do
38
+
39
+
40
+ @properties.each do |property|
41
+
42
+ # Set up a quick variable for checking if this property is a sale listing
43
+ property.class.name == "AllhomesXml::SaleListing" ? sale_listing = true : sale_listing = false
44
+
45
+ if sale_listing
46
+
47
+ # Attributes for the initial tag
48
+ listingAttributes = { :saleStatus => get_sale_status(property),
49
+ :uniqueId => "S#{property.id}"}
50
+
51
+ # If this property is sold, add the attributes to the initial tag
52
+ if property.exchange_date and property.sale_price
53
+ listingAttributes.update({:saleDate => property.exchange_date.strftime("%Y-%m-%d"), :salePrice => property.sale_price})
54
+ end
55
+
56
+ else
57
+
58
+ # Attributes for the initial tag
59
+ listingAttributes = { :rentalStatus => get_rent_status(property),
60
+ :uniqueId => "R#{property.id}"}
61
+
62
+ # If the property is rented, add the rented date and price
63
+ if property.rented and property.rented_date and property.rented_price
64
+ listingAttributes.update({:rentedDate => property.rented_date.strftime("%Y-%m-%d"), :rentedPrice => property.rented_price})
65
+ end
66
+
67
+ end
68
+
69
+ # Generate initial tag
70
+ if COMMERCIAL_PROPERTY_TYPES.include? property.property_type
71
+ sale_listing ? opening_tag = "commercialSaleListing" : opening_tag = "commercialRentalListing"
72
+ else
73
+ sale_listing ? opening_tag = "residentialSaleListing" : opening_tag = "residentialRentalListing"
74
+ end
75
+
76
+ # Opening Tag
77
+ ######################################################
78
+ xml.tag!(opening_tag, listingAttributes) do
79
+
80
+ # Agent Details
81
+ ######################################################
82
+ xml.agentDetails do
83
+ xml.agencyId property.agency_id
84
+ xml.primaryContact do
85
+ xml.firstName property.agents.primary_agent[:firstname]
86
+ xml.lastName property.agents.primary_agent[:surname]
87
+ end
88
+
89
+ if sale_listing
90
+ if property.agents.secondary_agent
91
+ xml.alternativeContact do
92
+ xml.firstName property.agents.secondary_agent[:firstname]
93
+ xml.lastName property.agents.secondary_agent[:surname]
94
+ end
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ # Street Address
101
+ ######################################################
102
+ xml.streetAddress do
103
+
104
+ xml.unitNumber property.unit_number unless property.unit_number.blank?
105
+ xml.streetNumber property.street_number unless (property.street_number =~ /^[&\w\- ]+$/).nil?
106
+ xml.streetName property.street_name
107
+ xml.streetType property.street_type.upcase
108
+ xml.propertyName property.complex unless property.complex.blank?
109
+ xml.suburb property.suburb
110
+ xml.postCode property.postcode
111
+ xml.state property.state
112
+ xml.country "Australia"
113
+
114
+ if property.hide_address
115
+ xml.addressVisibility "HIDE_STREET_NUMBER_AND_NAME"
116
+ else
117
+ xml.addressVisibility "VISIBLE"
118
+ end
119
+
120
+ end
121
+
122
+ # Formal Address - Sale Only
123
+ ######################################################
124
+ if sale_listing and property.state == 'ACT'
125
+
126
+ xml.formalAddress do
127
+
128
+ xml.blockSection do
129
+
130
+ if (property.block =~ /[^0-9]/).nil?
131
+ xml.block property.block
132
+ else
133
+ xml.block
134
+ end
135
+ xml.section property.section
136
+
137
+ end
138
+
139
+ # end
140
+
141
+ end
142
+
143
+ end
144
+
145
+ # Title and Description
146
+ ######################################################
147
+ xml.title property.title
148
+ if property.description.blank?
149
+ xml.description 'No description available.'
150
+ else
151
+ xml.description property.description
152
+ end
153
+
154
+ # EER
155
+ ######################################################
156
+ xml.eer property.eer if not property.eer.blank? and not property.eer == 'N/A'
157
+
158
+ # Street Directory Reference
159
+ ######################################################
160
+ xml.streetDirectoryReference do
161
+
162
+ xml.type ""
163
+ xml.reference ""
164
+
165
+ end
166
+
167
+ # Listing Status
168
+ ######################################################
169
+ xml.listingStatus "active"
170
+
171
+ # Photos
172
+ ######################################################
173
+ unless property.photos.blank?
174
+
175
+ xml.images do
176
+
177
+ property.photos.each do |photo|
178
+
179
+ xml.image do
180
+
181
+ xml.imageReference photo[:url]
182
+ xml.caption photo[:caption] unless photo[:caption].blank?
183
+ xml.orderIndex photo[:order]
184
+
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+
191
+ end
192
+
193
+ # Rental Availability - Rentals Only
194
+ ######################################################
195
+ if not sale_listing and (property.available_from or property.available_to)
196
+
197
+ xml.availability do
198
+
199
+ xml.from property.available_from.strftime("%Y-%m-%d") if property.available_from
200
+ xml.to property.available_to.strftime("%Y-%m-%d") if property.available_to
201
+
202
+ end
203
+
204
+ end
205
+
206
+ # Sale Authority - Sale Only
207
+ ######################################################
208
+ xml.saleAuthority "exclusive" if sale_listing
209
+
210
+ # Price
211
+ ######################################################
212
+ if sale_listing
213
+
214
+ case property.price.class.name
215
+
216
+ # If the property is an auction
217
+ when "AllhomesXml::Price::Auction"
218
+
219
+ xml.auction do
220
+
221
+ xml.date property.price.date.strftime("%Y-%m-%d")
222
+ xml.startTime property.price.start.strftime("%H:%M:%S")
223
+ xml.unpublishedPriceEstimate property.price.estimate unless property.price.estimate.blank?
224
+
225
+ end
226
+
227
+ # If the property is by tender
228
+ when "AllhomesXml::Price::Tender"
229
+
230
+ xml.tender do
231
+
232
+ xml.closingDate property.price.date.xmlschema
233
+
234
+ end
235
+
236
+ # If the property is by Expressions of Interest
237
+ when "AllhomesXml::Price::EOI"
238
+
239
+ xml.expressionOfInterest do
240
+
241
+ xml.closingDate property.price.date.xmlschema
242
+
243
+ end
244
+
245
+ # If the property is sold by plain old price
246
+ when "AllhomesXml::Price::Range"
247
+
248
+ xml.price do
249
+
250
+ xml.lower property.price.low
251
+ xml.upper property.price.high
252
+
253
+ end
254
+
255
+ when "AllhomesXml::Price::Fixed"
256
+
257
+ xml.price do
258
+
259
+ xml.lower property.price.price
260
+ property.offers_over ? xml.offersAbove("true") : xml.offersAbove("false")
261
+
262
+ end
263
+
264
+ # If the property is by negotiation
265
+ else
266
+
267
+ xml.price ""
268
+
269
+ end
270
+
271
+ # If rental listing
272
+ else
273
+
274
+ xml.price do
275
+
276
+ xml.lower property.price unless property.price.blank?
277
+ xml.paymentPeriod "weekly" unless property.price.blank?
278
+
279
+ end
280
+
281
+ end
282
+
283
+ # Exhibitions
284
+ ##################
285
+ unless property.exhibitions.blank?
286
+
287
+ xml.exhibitions do
288
+
289
+ property.exhibitions.each do |opentime|
290
+
291
+ xml.exhibition do
292
+
293
+ xml.date opentime[:date].strftime("%Y-%m-%d")
294
+ xml.startTime opentime[:start].strftime("%H:%M:%S")
295
+ xml.endTime opentime[:finish].strftime("%H:%M:%S")
296
+
297
+ end
298
+
299
+ end
300
+
301
+ end
302
+
303
+ end
304
+
305
+ # Rental Purpose
306
+ ##################
307
+ xml.rentalPurpose 'residential' if not sale_listing and not COMMERCIAL_PROPERTY_TYPES.include?(property.property_type)
308
+
309
+ # Property Details
310
+ ##################
311
+ xml.propertyDetails do
312
+
313
+ # House & Block Size
314
+ ##################
315
+ xml.buildingDetails do
316
+
317
+ if sale_listing and property.floor_area and not property.floor_area.to_f == 0
318
+
319
+ xml.buildingSize property.floor_area.to_f
320
+
321
+ end
322
+
323
+ end
324
+
325
+ xml.landDetails do
326
+
327
+ xml.blockSize property.block_size if sale_listing and property.block_size and (property.block_size =~ /[^0-9.]/).nil?
328
+
329
+ end
330
+
331
+ # UV
332
+ ##################
333
+ xml.unimprovedLandValue(property.uv) if sale_listing and not property.uv.blank?
334
+
335
+ # Property Type
336
+ ##################
337
+ xml.propertyType property.property_type
338
+
339
+ # Features
340
+ ##################
341
+ # If we're not dealing with a commercial property, output the features
342
+ unless COMMERCIAL_PROPERTY_TYPES.include? property.property_type
343
+
344
+ # Features unique to sales / rentals
345
+ features = {}
346
+ if sale_listing
347
+ features['coreArea'] = true if property.core_area
348
+ features['bodyCorporate'] = true if property.body_corporate
349
+ features['plansApproved'] = true if property.plans_approved
350
+ else
351
+ features['petsAllowed'] = true if property.pets_allowed
352
+ features['shortTermLease'] = true if property.short_term_lease
353
+ end
354
+
355
+ # Features common to both sales / rentals
356
+ features[:bedrooms] = property.bedrooms unless property.bedrooms.blank?
357
+ features[:bathrooms] = property.bathrooms unless property.bathrooms.blank?
358
+ features[:ensuites] = property.ensuites unless property.ensuites.blank?
359
+ features[:carportSpaces] = property.carspaces unless property.carspaces.blank?
360
+ features[:garageSpaces] = property.garagespaces unless property.garagespaces.blank?
361
+
362
+ # Merge extra attributes
363
+ features.update property.attributes
364
+
365
+ # Features tag
366
+ xml.features features
367
+
368
+ end
369
+
370
+ end
371
+
372
+ end
373
+
374
+ end
375
+
376
+ end
377
+
378
+ end
379
+
380
+ protected
381
+
382
+ def get_sale_status property
383
+
384
+ if property.sold
385
+ 'sold'
386
+ else
387
+ if property.withdrawn
388
+ 'withdrawn'
389
+ elsif property.under_offer
390
+ 'underOffer'
391
+ else
392
+ 'forSale'
393
+ end
394
+ end
395
+
396
+ end
397
+
398
+ def get_rent_status property
399
+
400
+ if property.rented
401
+ 'rented'
402
+ else
403
+ if property.withdrawn
404
+ 'withdrawn'
405
+ elsif property.under_application
406
+ 'underApplication'
407
+ else
408
+ 'forRent'
409
+ end
410
+ end
411
+
412
+ end
413
+
414
+ end
415
+
416
+ end