Skip to content

Commit

Permalink
feat: add Batch Offer Requests (#12)
Browse files Browse the repository at this point in the history
* fix(duffel): fix panic when req.Body == nil

* feat: add Batch Offer Requests
  • Loading branch information
0x9ef authored May 2, 2024
1 parent 58d7224 commit 4421b93
Show file tree
Hide file tree
Showing 7 changed files with 456 additions and 12 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,6 @@

# Dependency directories (remove the comment below to include it)
# vendor/
*.DS_store
examples/.DS_Store
.DS_Store
45 changes: 45 additions & 0 deletions batchofferrequests.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
package duffel

import (
"context"
)

type (
BatchOfferRequestClient interface {
CreateBatchOfferRequest(ctx context.Context, requestInput CreateBatchOfferRequestInput) (*BatchOfferRequest, error)
GetBatchOfferRequest(ctx context.Context, id string) (*BatchOfferRequest, error)
}

CreateBatchOfferRequestInput struct {
// The passengers who want to travel. If you specify an age for a passenger, the type may differ for the same passenger in different offers due to airline's different rules. e.g. one airline may treat a 14 year old as an adult, and another as a young adult. You may only specify an age or a type – not both.
Passengers []OfferRequestPassenger `json:"passengers" url:"-"`
// The slices that make up this offer request. One-way journeys can be expressed using one slice, whereas return trips will need two.
Slices []OfferRequestSlice `json:"slices" url:"-"`
// The cabin that the passengers want to travel in
CabinClass CabinClass `json:"cabin_class" url:"-"`
// The maximum number of connections within any slice of the offer. For example 0 means a direct flight which will have a single segment within each slice and 1 means a maximum of two segments within each slice of the offer.
MaxConnections *int `json:"max_connections,omitempty" url:"-"`
// The maximum amount of time in milliseconds to wait for each airline to respond
SupplierTimeout int `json:"-" url:"supplier_timeout,omitempty"`
}

BatchOfferRequest struct {
TotalBatches int `json:"total_batches"`
RemainingBatches int `json:"remaining_batches"`
ID string `json:"id"`
Offers []Offer `json:"offers,omitempty"`
CreatedAt DateTime `json:"created_at"`
}
)

func (a *API) CreateBatchOfferRequest(ctx context.Context, requestInput CreateBatchOfferRequestInput) (*BatchOfferRequest, error) {
return newRequestWithAPI[CreateBatchOfferRequestInput, BatchOfferRequest](a).
Post("/air/batch_offer_requests", &requestInput).
Single(ctx)
}

func (a *API) GetBatchOfferRequest(ctx context.Context, id string) (*BatchOfferRequest, error) {
return newRequestWithAPI[EmptyPayload, BatchOfferRequest](a).
Getf("/air/batch_offer_requests/%s", id).
Single(ctx)
}
76 changes: 76 additions & 0 deletions batchofferrequests_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
package duffel

import (
"context"
"testing"
"time"

"github.com/stretchr/testify/assert"
"gopkg.in/h2non/gock.v1"
)

func TestCreateBatchOfferRequest(t *testing.T) {
defer gock.Off()
a := assert.New(t)
gock.New("https://api.duffel.com").
Post("/air/batch_offer_requests").
Reply(200).
SetHeader("Ratelimit-Limit", "5").
SetHeader("Ratelimit-Remaining", "5").
SetHeader("Ratelimit-Reset", time.Now().Format(time.RFC1123)).
SetHeader("Date", time.Now().Format(time.RFC1123)).
File("fixtures/200-create-batch-offer-request.json")

ctx := context.TODO()

client := New("duffel_test_123")
data, err := client.CreateBatchOfferRequest(ctx, CreateBatchOfferRequestInput{
Passengers: []OfferRequestPassenger{
{
FamilyName: "Earhardt",
GivenName: "Amelia",
Type: PassengerTypeAdult,
},
{
Age: 14,
},
},
CabinClass: CabinClassEconomy,
Slices: []OfferRequestSlice{
{
DepartureDate: Date(time.Now().AddDate(0, 0, 7)),
Origin: "JFK",
Destination: "AUS",
},
},
})
a.NoError(err)
a.NotNil(data)

a.Equal(7, data.RemainingBatches)
a.Equal(7, data.TotalBatches)
}

func TestGetBatchOfferRequest(t *testing.T) {
defer gock.Off()
a := assert.New(t)
gock.New("https://api.duffel.com").
Get("/air/batch_offer_requests/orq_0000AhTmH2Thpl6RrM97qK").
Reply(200).
SetHeader("Ratelimit-Limit", "5").
SetHeader("Ratelimit-Remaining", "5").
SetHeader("Ratelimit-Reset", time.Now().Format(time.RFC1123)).
SetHeader("Date", time.Now().Format(time.RFC1123)).
File("fixtures/200-get-batch-offer-request.json")

ctx := context.TODO()

client := New("duffel_test_123")

data, err := client.GetBatchOfferRequest(ctx, "orq_0000AhTmH2Thpl6RrM97qK")
a.NoError(err)
a.NotNil(data)

a.Equal(2, data.TotalBatches)
a.Equal(2, data.RemainingBatches)
}
12 changes: 1 addition & 11 deletions duffel.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ const defaultHost = "https://api.duffel.com/"
type (
Duffel interface {
OfferRequestClient
BatchOfferRequestClient
PartialOfferRequestClient
OfferClient
OrderClient
Expand All @@ -30,8 +31,6 @@ type (
PlacesClient

LastRequestID() (string, bool)
LastResponse() *http.Response
GetClient() *http.Client
}

Gender string
Expand Down Expand Up @@ -275,7 +274,6 @@ type (
APIToken string
options *Options
lastRequestID string
lastResponse *http.Response
}
)

Expand Down Expand Up @@ -330,14 +328,6 @@ func (a *API) LastRequestID() (string, bool) {
return a.lastRequestID, a.lastRequestID != ""
}

func (a *API) LastResponse() *http.Response {
return a.lastResponse
}

func (a *API) GetClient() *http.Client {
return a.httpDoer
}

// Assert that our interface matches
var (
_ Duffel = (*API)(nil)
Expand Down
10 changes: 10 additions & 0 deletions fixtures/200-create-batch-offer-request.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
{
"data": {
"remaining_batches": 7,
"total_batches": 7,
"client_key": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjE3MTQ3MzU4NDAsImxpdmVfbW9kZSI6ZmFsc2UsIm9yZ2FuaXNhdGlvbl9pZCI6Im9yZ18wMDAwQU4xdXZobHNaQlF6RDhPSTFZIn0.1dOy3eTaUskIgfphTgAlW0aStrwklPModabSf-Znam0",
"created_at": "2024-05-02T11:30:40.589820Z",
"live_mode": false,
"id": "orq_0000AhTmH2Thpl6RrM97qK"
}
}
Loading

0 comments on commit 4421b93

Please sign in to comment.