qpx agent

This commit is contained in:
Judy Ngai 2016-03-23 17:34:03 -04:00
parent 1d07bca221
commit c02f32207e
3 changed files with 201 additions and 25 deletions

View file

@ -6,7 +6,7 @@ module Agents
description <<-MD
The QpxExpressAgent will tell you airline prices between a pair of cities. The api limit is 50 requests/day.
The QpxExpressAgent will tell you the minimum airline prices between a pair of cities. The api limit is 50 requests/day.
Follow their documentation here (https://developers.google.com/qpx-express/v1/prereqs#get-a-google-account) to retrieve an api key.
After you get to the google developer console, created a project, enabled qpx express api then you can choose `api key` credential to be created.
@ -15,9 +15,9 @@ module Agents
All the default options must exist. For `infantInSeatCount`, `infantInLapCount`, `seniorCount`, and `childCount`, leave them to the default value of `0` if its not necessary.
Set `refundable` to `true` if you want ticket to be refundable. Make sure `date` is in this type of date format `YYYY-MO-DAY`.
Make sure `date` is in this type of date format `YYYY-MO-DAY`.
You can limit the number of `solutions` returned back. The first solution is the lowest priced ticket. Every detailed trip option details starts at `"slice"`.
You can limit the number of `solutions` returned back. The first solution is the lowest priced ticket.
MD
event_description <<-MD
@ -46,17 +46,16 @@ module Agents
def default_options
{
'qpx_api_key': '',
'adultCount': 1,
'origin': 'BOS',
'destination': 'SFO',
'date': '2016-04-11',
'childCount': 0,
'infantInSeatCount': 0,
'infantInLapCount': 0,
'seniorCount': 0,
'solutions': 3,
'refundable': false
'qpx_api_key' => '',
'adultCount'=> 1,
'origin' => 'BOS',
'destination' => 'SFO',
'date' => '2016-04-11',
'childCount' => 0,
'infantInSeatCount' => 0,
'infantInLapCount'=> 0,
'seniorCount'=> 0,
'solutions'=> 3
}
end
@ -71,7 +70,6 @@ module Agents
errors.add(:base, "Infant In Lap Count") unless options['infantInLapCount'].present?
errors.add(:base, "Senior Count must exist") unless options['seniorCount'].present?
errors.add(:base, "Solutions must exist") unless options['solutions'].present?
errors.add(:base, "Refundable must exist") unless options['refundable'].present?
end
def working?
@ -79,7 +77,7 @@ module Agents
end
def check
post_params = {:request=>{:passengers=>{:kind=>"qpxexpress#passengerCounts", :adultCount=> interpolated["adultCount"], :childCount=> interpolated["childCount"], :infantInLapCount=>interpolated["infantInLapCount"], :infantInSeatCount=>interpolated['infantInSeatCount'], :seniorCount=>interpolated["seniorCount"]}, :slice=>[{:kind=>"qpxexpress#sliceInput", :origin=> interpolated["origin"].to_s , :destination=> interpolated["destination"].to_s , :date=> interpolated["date"].to_s }], :refundable=> interpolated["refundable"], :solutions=> interpolated["solutions"]}}
post_params = {:request=>{:passengers=>{:kind=>"qpxexpress#passengerCounts", :adultCount=> interpolated["adultCount"], :childCount=> interpolated["childCount"], :infantInLapCount=>interpolated["infantInLapCount"], :infantInSeatCount=>interpolated['infantInSeatCount'], :seniorCount=>interpolated["seniorCount"]}, :slice=>[{:kind=>"qpxexpress#sliceInput", :origin=> interpolated["origin"].to_s , :destination=> interpolated["destination"].to_s , :date=> interpolated["date"].to_s }], :solutions=> interpolated["solutions"]}}
body = JSON.generate(post_params)
request = HTTParty.post(event_url, :body => body, :headers => {"Content-Type" => "application/json"})
events = JSON.parse request.body

184
spec/data_fixtures/qpx.json Normal file
View file

@ -0,0 +1,184 @@
{
"kind": "qpxExpress#tripsSearch",
"trips": {
"kind": "qpxexpress#tripOptions",
"requestId": "a5KWNgUILMQXl0QjZ0O1Kj",
"data": {
"kind": "qpxexpress#data",
"airport": [
{
"kind": "qpxexpress#airportData",
"code": "BOS",
"city": "BOS",
"name": "Boston Logan International"
},
{
"kind": "qpxexpress#airportData",
"code": "SFO",
"city": "SFO",
"name": "San Francisco International"
}
],
"city": [
{
"kind": "qpxexpress#cityData",
"code": "BOS",
"name": "Boston"
},
{
"kind": "qpxexpress#cityData",
"code": "SFO",
"name": "San Francisco"
}
],
"aircraft": [
{
"kind": "qpxexpress#aircraftData",
"code": "320",
"name": "Airbus A320"
}
],
"tax": [
{
"kind": "qpxexpress#taxData",
"id": "ZP",
"name": "US Flight Segment Tax"
},
{
"kind": "qpxexpress#taxData",
"id": "AY_001",
"name": "US September 11th Security Fee"
},
{
"kind": "qpxexpress#taxData",
"id": "US_001",
"name": "US Transportation Tax"
},
{
"kind": "qpxexpress#taxData",
"id": "XF",
"name": "US Passenger Facility Charge"
}
],
"carrier": [
{
"kind": "qpxexpress#carrierData",
"code": "B6",
"name": "Jetblue Airways Corporation"
}
]
},
"tripOption": [
{
"kind": "qpxexpress#tripOption",
"saleTotal": "USD244.10",
"id": "SD5atWDaIWFUAOehDmedl8001",
"slice": [
{
"kind": "qpxexpress#sliceInfo",
"duration": 404,
"segment": [
{
"kind": "qpxexpress#segmentInfo",
"duration": 404,
"flight": {
"carrier": "B6",
"number": "833"
},
"id": "Gv+0Syg7VaA8NyWp",
"cabin": "COACH",
"bookingCode": "Z",
"bookingCodeCount": 7,
"marriedSegmentGroup": "0",
"leg": [
{
"kind": "qpxexpress#legInfo",
"id": "LXRlPXVU35MvdfE-",
"aircraft": "320",
"arrivalTime": "2016-04-11T23:10-07:00",
"departureTime": "2016-04-11T19:26-04:00",
"origin": "BOS",
"destination": "SFO",
"originTerminal": "C",
"destinationTerminal": "I",
"duration": 404,
"onTimePerformance": 60,
"mileage": 2697,
"secure": true
}
]
}
]
}
],
"pricing": [
{
"kind": "qpxexpress#pricingInfo",
"fare": [
{
"kind": "qpxexpress#fareInfo",
"id": "Aw9SUGx6XiV/Eeby73yJz5cu1avySnHVCBCW01QV6wk2",
"carrier": "B6",
"origin": "BOS",
"destination": "SFO",
"basisCode": "ZH4AUEN"
}
],
"segmentPricing": [
{
"kind": "qpxexpress#segmentPricing",
"fareId": "Aw9SUGx6XiV/Eeby73yJz5cu1avySnHVCBCW01QV6wk2",
"segmentId": "Gv+0Syg7VaA8NyWp"
}
],
"baseFareTotal": "USD213.95",
"saleFareTotal": "USD213.95",
"saleTaxTotal": "USD30.15",
"saleTotal": "USD244.10",
"passengers": {
"kind": "qpxexpress#passengerCounts",
"adultCount": 1
},
"tax": [
{
"kind": "qpxexpress#taxInfo",
"id": "US_001",
"chargeType": "GOVERNMENT",
"code": "US",
"country": "US",
"salePrice": "USD16.05"
},
{
"kind": "qpxexpress#taxInfo",
"id": "AY_001",
"chargeType": "GOVERNMENT",
"code": "AY",
"country": "US",
"salePrice": "USD5.60"
},
{
"kind": "qpxexpress#taxInfo",
"id": "XF",
"chargeType": "GOVERNMENT",
"code": "XF",
"country": "US",
"salePrice": "USD4.50"
},
{
"kind": "qpxexpress#taxInfo",
"id": "ZP",
"chargeType": "GOVERNMENT",
"code": "ZP",
"country": "US",
"salePrice": "USD4.00"
}
],
"fareCalculation": "BOS B6 SFO 213.95ZH4AUEN USD 213.95 END ZP BOS XT 16.05US 4.00ZP 5.60AY 4.50XF BOS4.50",
"latestTicketingTime": "2016-03-24T23:59-04:00",
"ptc": "ADT"
}
]
}
]
}
}

View file

@ -3,7 +3,7 @@ require 'rails_helper'
describe Agents::QpxAgent do
before do
stub_request(:get, "https://www.googleapis.com/qpxExpress/v1/trips/search").to_return(
stub_request(:post, "https://www.googleapis.com/qpxExpress/v1/trips/search?key=800deeaf-e285-9d62-bc90-j999c1973cc9").to_return(
:body => File.read(Rails.root.join("spec/data_fixtures/qpx.json")),
:status => 200,
:headers => {"Content-Type" => "application/json"}
@ -19,7 +19,6 @@ describe Agents::QpxAgent do
'infantInSeatCount' => 0,
'infantInLapCount'=> 0,
'seniorCount'=> 0,
'refundable' => false,
'solutions'=> 3
}
@ -35,7 +34,7 @@ describe Agents::QpxAgent do
end
describe "#that checker should be valid" do
it "should check that the aftership object is valid" do
it "should check that the object is valid" do
expect(@checker).to be_valid
end
@ -88,16 +87,11 @@ describe Agents::QpxAgent do
@checker.options['solutions'] = nil
expect(@checker).not_to be_valid
end
it "should require Refundable" do
@checker.options['refundable'] = nil
expect(@checker).not_to be_valid
end
end
describe '#check' do
it "should check that initial run creates an event" do
@checker.memory[:latestTicketingTime] = '2016-03-18T23:59-04:00'
@checker.memory[:latestTicketingTime] = '2016-03-24T23:59-04:00'
expect { @checker.check }.to change { Event.count }.by(1)
end
end