diff --git a/CHANGELOG.md b/CHANGELOG.md index 92d378a..c607107 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,6 +2,7 @@ ## Next Release +- Adds new `EstimateDeliveryDateForZipPair`, `RecommendShipDateForShipment` and `RecommendShipDateForZipPair` - New `CreateUpsCarrierAccount` and `UpdateUpsCarrierAccount` methods and associated parameter structs, required to use for UPS accounts due to new `/ups_oauth_registrations` endpoint. - Starting `2024-08-05`, UPS accounts will require a new payload to register or update. See [UPS OAuth 2.0 Update](https://support.easypost.com/hc/en-us/articles/26635027512717-UPS-OAuth-2-0-Update) for more details. - Attempting to use the generic `CreateCarrierAccount` and `UpdateCarrierAccount` methods with UPS accounts will throw an `InvalidFunctionError`. diff --git a/datetime.go b/datetime.go index 07c5a70..daed6ab 100644 --- a/datetime.go +++ b/datetime.go @@ -16,75 +16,10 @@ func (dt *DateTime) UnmarshalJSON(b []byte) (err error) { var t time.Time // try to parse - // 2006-01-02 - t, err = time.Parse(`"2006-01-02"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse - // 2006-01-02T15:04:05Z - t, err = time.Parse(`"2006-01-02T15:04:05Z"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC3339 (default for time.Time) - // 2006-01-02T15:04:05Z07:00 - t, err = time.Parse(`"`+time.RFC3339+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC3339Nano - // 2006-01-02T15:04:05.999999999Z07:00 - t, err = time.Parse(`"`+time.RFC3339Nano+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC1123 - // Mon, 02 Jan 2006 15:04:05 MST - t, err = time.Parse(`"`+time.RFC1123+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC1123Z - // Mon, 02 Jan 2006 15:04:05 -0700 - t, err = time.Parse(`"`+time.RFC1123Z+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC822 - // 02 Jan 06 15:04 MST - t, err = time.Parse(`"`+time.RFC822+`"`, string(b)) + asDateTime, err := DateTimeFromString(string(b)) if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC822Z - // 02 Jan 06 15:04 -0700 - t, err = time.Parse(`"`+time.RFC822Z+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return - } - - // try to parse as RFC850 - // Monday, 02-Jan-06 15:04:05 MST - t, err = time.Parse(`"`+time.RFC850+`"`, string(b)) - if err == nil { - *dt = DateTime(t) - return + *dt = asDateTime + return nil } // last ditch effort, fallback to whatever the JSON marshaller thinks @@ -141,3 +76,81 @@ func NewDateTime(year int, month time.Month, day, hour, min, sec, nsec int, loc func DateTimeFromTime(t time.Time) DateTime { return DateTime(t) } + +func DateTimeFromString(s string) (dt DateTime, err error) { + var t time.Time + + // try to parse + // 2006-01-02 + t, err = time.Parse(`"2006-01-02"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse + // 2006-01-02T15:04:05Z + t, err = time.Parse(`"2006-01-02T15:04:05Z"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC3339 (default for time.Time) + // 2006-01-02T15:04:05Z07:00 + t, err = time.Parse(`"`+time.RFC3339+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC3339Nano + // 2006-01-02T15:04:05.999999999Z07:00 + t, err = time.Parse(`"`+time.RFC3339Nano+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC1123 + // Mon, 02 Jan 2006 15:04:05 MST + t, err = time.Parse(`"`+time.RFC1123+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC1123Z + // Mon, 02 Jan 2006 15:04:05 -0700 + t, err = time.Parse(`"`+time.RFC1123Z+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC822 + // 02 Jan 06 15:04 MST + t, err = time.Parse(`"`+time.RFC822+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC822Z + // 02 Jan 06 15:04 -0700 + t, err = time.Parse(`"`+time.RFC822Z+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + // try to parse as RFC850 + // Monday, 02-Jan-06 15:04:05 MST + t, err = time.Parse(`"`+time.RFC850+`"`, s) + if err == nil { + dt = DateTime(t) + return + } + + return +} diff --git a/shipment.go b/shipment.go index d281a76..1b1494e 100644 --- a/shipment.go +++ b/shipment.go @@ -125,6 +125,12 @@ type EstimatedDeliveryDate struct { Rate SmartRate `json:"rate,omitempty"` } +// RecommendShipDateForShipmentResult is the result of the RecommendShipDateForShipment method. +type RecommendShipDateForShipmentResult struct { + Rate *SmartRate `json:"rate,omitempty"` + EasyPostTimeInTransitData *TimeInTransitDetailsForShipDate `json:"easypost_time_in_transit_data,omitempty"` +} + // CreateShipment creates a new Shipment object. The ToAddress, FromAddress and // Parcel attributes are required. These objects may be fully-specified to // create new ones at the same time as creating the Shipment, or they can refer @@ -385,13 +391,12 @@ func (c *Client) GenerateShipmentFormWithOptionsWithContext(ctx context.Context, return } -// GetShipmentEstimatedDeliveryDate retrieves the estimated delivery date of each Rate via SmartRate. -func (c *Client) GetShipmentEstimatedDeliveryDate(shipmentID, plannedShipDate string) (out []*EstimatedDeliveryDate, err error) { +// GetShipmentEstimatedDeliveryDate retrieves the estimated delivery date of each rate for a Shipment via the Delivery Date Estimator API, based on a specific ship date. +func (c *Client) GetShipmentEstimatedDeliveryDate(shipmentID string, plannedShipDate string) (out []*EstimatedDeliveryDate, err error) { return c.GetShipmentEstimatedDeliveryDateWithContext(context.Background(), shipmentID, plannedShipDate) } -// GetShipmentEstimatedDeliveryDateWithContext performs the same operation as GetShipmentEstimatedDeliveryDate, -// but allows specifying a context that can interrupt the request. +// GetShipmentEstimatedDeliveryDateWithContext performs the same operation as EstimateDeliveryDateForShipment, but allows specifying a context that can interrupt the request. func (c *Client) GetShipmentEstimatedDeliveryDateWithContext(ctx context.Context, shipmentID string, plannedShipDate string) (out []*EstimatedDeliveryDate, err error) { vals := url.Values{"planned_ship_date": []string{plannedShipDate}} res := struct { @@ -400,3 +405,18 @@ func (c *Client) GetShipmentEstimatedDeliveryDateWithContext(ctx context.Context err = c.do(ctx, http.MethodGet, "shipments/"+shipmentID+"/smartrate/delivery_date", vals, &res) return } + +// RecommendShipDateForShipment retrieves the recommended ship date of each rate for a Shipment via the Precision Shipping API, based on a specific desired delivery date. +func (c *Client) RecommendShipDateForShipment(shipmentID string, desiredDeliveryDate string) (out []*RecommendShipDateForShipmentResult, err error) { + return c.RecommendShipDateForShipmentWithContext(context.Background(), shipmentID, desiredDeliveryDate) +} + +// RecommendShipDateForShipmentWithContext performs the same operation as RecommendShipDateForShipment, but allows specifying a context that can interrupt the request. +func (c *Client) RecommendShipDateForShipmentWithContext(ctx context.Context, shipmentID string, desiredDeliveryDate string) (out []*RecommendShipDateForShipmentResult, err error) { + vals := url.Values{"desired_delivery_date": []string{desiredDeliveryDate}} + res := struct { + Results *[]*RecommendShipDateForShipmentResult `json:"rates,omitempty"` + }{Results: &out} + err = c.do(ctx, http.MethodGet, "shipments/"+shipmentID+"/smartrate/precision_shipping", vals, &res) + return +} diff --git a/smart_rate.go b/smart_rate.go new file mode 100644 index 0000000..6e70719 --- /dev/null +++ b/smart_rate.go @@ -0,0 +1,95 @@ +package easypost + +import ( + "context" +) + +// TimeInTransitDetailsForDeliveryDate contains the time-in-transit details and estimated delivery date for a specific DeliveryDateForZipPairEstimate. +type TimeInTransitDetailsForDeliveryDate struct { + PlannedShipDate *DateTime `json:"planned_ship_date,omitempty"` + EasyPostEstimatedDeliveryDate *DateTime `json:"easypost_estimated_delivery_date,omitempty"` + DaysInTransit *TimeInTransit `json:"days_in_transit,omitempty"` +} + +// DeliveryDateForZipPairEstimate is a single zip-pair-based delivery date estimate for a carrier-service level combination. +type DeliveryDateForZipPairEstimate struct { + Carrier string `json:"carrier,omitempty"` + Service string `json:"service,omitempty"` + EasyPostTimeInTransitData *TimeInTransitDetailsForDeliveryDate `json:"easypost_time_in_transit_data,omitempty"` +} + +// EstimateDeliveryDateForZipPairResult is the result of the EstimateDeliveryDateForZipPair method, containing the estimated delivery date of each carrier-service level combination and additional metadata. +type EstimateDeliveryDateForZipPairResult struct { + CarriersWithoutEstimates []string `json:"carriers_without_tint_estimates,omitempty"` + FromZip string `json:"from_zip,omitempty"` + ToZip string `json:"to_zip,omitempty"` + SaturdayDelivery bool `json:"saturday_delivery,omitempty"` + PlannedShipDate *DateTime `json:"planned_ship_date,omitempty"` + Results []*DeliveryDateForZipPairEstimate `json:"results,omitempty"` +} + +// EstimateDeliveryDateForZipPairParams are used in the EstimateDeliveryDateForZipPair method. +type EstimateDeliveryDateForZipPairParams struct { + FromZip string `json:"from_zip,omitempty"` + ToZip string `json:"to_zip,omitempty"` + Carriers []string `json:"carriers,omitempty"` + PlannedShipDate string `json:"planned_ship_date,omitempty"` + SaturdayDelivery bool `json:"saturday_delivery,omitempty"` +} + +// TimeInTransitDetailsForShipDate contains the time-in-transit details and estimated delivery date for a specific ShipDateForZipPairRecommendation or RecommendShipDateForShipmentResult. +type TimeInTransitDetailsForShipDate struct { + DesiredDeliveryDate *DateTime `json:"desired_delivery_date,omitempty"` + EasyPostRecommendedShipDate *DateTime `json:"ship_on_date,omitempty"` + DeliveryDateConfidence float64 `json:"delivery_date_confidence,omitempty"` + EstimatedTransitDays int `json:"estimated_transit_days,omitempty"` + DaysInTransit *TimeInTransit `json:"days_in_transit,omitempty"` +} + +// ShipDateForZipPairRecommendation is a single zip-pair-based ship date recommendation for a carrier-service level combination. +type ShipDateForZipPairRecommendation struct { + Carrier string `json:"carrier,omitempty"` + Service string `json:"service,omitempty"` + EasyPostTimeInTransitData *TimeInTransitDetailsForShipDate `json:"easypost_time_in_transit_data,omitempty"` +} + +// RecommendShipDateForZipPairResult is the result of the RecommendShipDateForZipPair method, containing the recommended ship date of each carrier-service level combination and additional metadata. +type RecommendShipDateForZipPairResult struct { + CarriersWithoutEstimates []string `json:"carriers_without_tint_estimates,omitempty"` + FromZip string `json:"from_zip,omitempty"` + ToZip string `json:"to_zip,omitempty"` + SaturdayDelivery bool `json:"saturday_delivery,omitempty"` + DesiredDeliveryDate *DateTime `json:"desired_delivery_date,omitempty"` + Results []*ShipDateForZipPairRecommendation `json:"results,omitempty"` +} + +// RecommendShipDateForZipPairParams are used in the RecommendShipDateForZipPair method. +type RecommendShipDateForZipPairParams struct { + FromZip string `json:"from_zip,omitempty"` + ToZip string `json:"to_zip,omitempty"` + Carriers []string `json:"carriers,omitempty"` + DesiredDeliveryDate string `json:"desired_delivery_date,omitempty"` + SaturdayDelivery bool `json:"saturday_delivery,omitempty"` +} + +// EstimateDeliveryDateForZipPair retrieves the estimated delivery date of each carrier-service level combination via the Smart Deliver By API, based on a specific ship date and origin-destination postal code pair. +func (c *Client) EstimateDeliveryDateForZipPair(params *EstimateDeliveryDateForZipPairParams) (out *EstimateDeliveryDateForZipPairResult, err error) { + return c.EstimateDeliveryDateForZipPairWithContext(context.Background(), params) +} + +// EstimateDeliveryDateForZipPairWithContext performs the same operation as EstimateDeliveryDateForZipPair, but allows specifying a context that can interrupt the request. +func (c *Client) EstimateDeliveryDateForZipPairWithContext(ctx context.Context, params *EstimateDeliveryDateForZipPairParams) (out *EstimateDeliveryDateForZipPairResult, err error) { + err = c.post(ctx, "smartrate/deliver_by", params, &out) + return +} + +// RecommendShipDateForZipPair retrieves the recommended ship date of each carrier-service level combination via the Smart Deliver On API, based on a specific desired delivery date and origin-destination postal code pair. +func (c *Client) RecommendShipDateForZipPair(params *RecommendShipDateForZipPairParams) (out *RecommendShipDateForZipPairResult, err error) { + return c.RecommendShipDateForZipPairWithContext(context.Background(), params) +} + +// RecommendShipDateForZipPairWithContext performs the same operation as RecommendShipDateForZipPair, but allows specifying a context that can interrupt the request. +func (c *Client) RecommendShipDateForZipPairWithContext(ctx context.Context, params *RecommendShipDateForZipPairParams) (out *RecommendShipDateForZipPairResult, err error) { + err = c.post(ctx, "smartrate/deliver_on", params, &out) + return +} diff --git a/tests/cassettes/TestEstimateDeliveryDateForZipPair.yaml b/tests/cassettes/TestEstimateDeliveryDateForZipPair.yaml new file mode 100644 index 0000000..629303a --- /dev/null +++ b/tests/cassettes/TestEstimateDeliveryDateForZipPair.yaml @@ -0,0 +1,56 @@ +--- +version: 1 +interactions: +- request: + body: '{"carriers":["USPS"],"from_zip":"94107","planned_ship_date":"2024-07-17","to_zip":"90277"}' + form: {} + headers: + Authorization: + - REDACTED + Content-Type: + - application/json + User-Agent: + - REDACTED + url: https://api.easypost.com/v2/smartrate/deliver_by + method: POST + response: + body: '{"carriers_without_tint_estimates":null,"from_zip":"94107","planned_ship_date":"2024-07-17","results":[{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":1,"percentile_75":2,"percentile_85":2,"percentile_90":3,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2024-07-18"},"service":"express"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":9},"easypost_estimated_delivery_date":"2024-07-19"},"service":"groundadvantage"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":9},"easypost_estimated_delivery_date":"2024-07-19"},"service":"librarymail"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":7,"percentile_99":10},"easypost_estimated_delivery_date":"2024-07-20"},"service":"mediamail"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":8},"easypost_estimated_delivery_date":"2024-07-19"},"service":"priority"}],"saturday_delivery":null,"to_zip":"90277"}' + headers: + Cache-Control: + - private, no-cache, no-store + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Ep-Request-Uuid: + - 21ac78cf669182f1f3f85b04001051b9 + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb33nuq + X-Permitted-Cross-Domain-Policies: + - none + X-Proxied: + - intlb3nuq fa152d4755 + - extlb2nuq fa152d4755 + X-Runtime: + - "0.068583" + X-Version-Label: + - easypost-202407121702-a82cfb9ac3-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/tests/cassettes/TestRecommendShipDateForZipPair.yaml b/tests/cassettes/TestRecommendShipDateForZipPair.yaml new file mode 100644 index 0000000..7c09271 --- /dev/null +++ b/tests/cassettes/TestRecommendShipDateForZipPair.yaml @@ -0,0 +1,56 @@ +--- +version: 1 +interactions: +- request: + body: '{"carriers":["USPS"],"desired_delivery_date":"2024-07-17","from_zip":"94107","to_zip":"90277"}' + form: {} + headers: + Authorization: + - REDACTED + Content-Type: + - application/json + User-Agent: + - REDACTED + url: https://api.easypost.com/v2/smartrate/deliver_on + method: POST + response: + body: '{"carriers_without_tint_estimates":null,"desired_delivery_date":"2024-07-17","from_zip":"94107","results":[{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":1,"percentile_75":2,"percentile_85":2,"percentile_90":3,"percentile_95":3,"percentile_97":4,"percentile_99":6},"delivery_date_confidence":0.46,"estimated_transit_days":1,"ship_on_date":"2024-07-16"},"service":"express"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":3,"percentile_90":4,"percentile_95":4,"percentile_97":5,"percentile_99":8},"delivery_date_confidence":0.43,"estimated_transit_days":2,"ship_on_date":"2024-07-15"},"service":"groundadvantage"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":3,"percentile_90":4,"percentile_95":4,"percentile_97":5,"percentile_99":7},"delivery_date_confidence":0.47,"estimated_transit_days":2,"ship_on_date":"2024-07-15"},"service":"librarymail"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":3,"percentile_90":4,"percentile_95":4,"percentile_97":5,"percentile_99":7},"delivery_date_confidence":0.4,"estimated_transit_days":2,"ship_on_date":"2024-07-15"},"service":"mediamail"},{"carrier":"USPS","easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":3,"percentile_85":3,"percentile_90":4,"percentile_95":4,"percentile_97":5,"percentile_99":7},"delivery_date_confidence":0.49,"estimated_transit_days":2,"ship_on_date":"2024-07-15"},"service":"priority"}],"saturday_delivery":null,"to_zip":"90277"}' + headers: + Cache-Control: + - private, no-cache, no-store + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Ep-Request-Uuid: + - d02331d1669182e9f3f6ba64000fa82b + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb41nuq + X-Permitted-Cross-Domain-Policies: + - none + X-Proxied: + - intlb4nuq fa152d4755 + - extlb1nuq fa152d4755 + X-Runtime: + - "0.075750" + X-Version-Label: + - easypost-202407121702-a82cfb9ac3-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/tests/cassettes/TestShipmentGetShipmentEstimatedDeliveryDate.yaml b/tests/cassettes/TestShipmentGetShipmentEstimatedDeliveryDate.yaml index ffcfe21..8af97d6 100644 --- a/tests/cassettes/TestShipmentGetShipmentEstimatedDeliveryDate.yaml +++ b/tests/cassettes/TestShipmentGetShipmentEstimatedDeliveryDate.yaml @@ -19,19 +19,19 @@ interactions: method: POST response: body: '{"batch_id":null,"batch_message":null,"batch_status":null,"buyer_address":{"carrier_facility":null,"city":"Redondo - Beach","company":null,"country":"US","created_at":"2023-11-30T20:11:57+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_b68ff41e8fbc11ee91adac1f6bc539aa","mode":"test","name":"Elizabeth + Beach","company":null,"country":"US","created_at":"2024-07-12T19:41:46+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_c637342c408611ef87f33cecef1b359e","mode":"test","name":"Elizabeth Swan","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"179 - N Harbor Dr","street2":null,"updated_at":"2023-11-30T20:11:57+00:00","verifications":{},"zip":"90277"},"created_at":"2023-11-30T20:11:57Z","customs_info":null,"fees":[],"forms":[],"from_address":{"carrier_facility":null,"city":"San - Francisco","company":null,"country":"US","created_at":"2023-11-30T20:11:57+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_b6925f748fbc11ee830cac1f6bc53342","mode":"test","name":"Jack + N Harbor Dr","street2":null,"updated_at":"2024-07-12T19:41:46+00:00","verifications":{},"zip":"90277"},"created_at":"2024-07-12T19:41:46Z","customs_info":null,"fees":[],"forms":[],"from_address":{"carrier_facility":null,"city":"San + Francisco","company":null,"country":"US","created_at":"2024-07-12T19:41:46+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_c63a4efb408611efb412ac1f6bc539aa","mode":"test","name":"Jack Sparrow","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"388 - Townsend St","street2":"Apt 20","updated_at":"2023-11-30T20:11:57+00:00","verifications":{},"zip":"94107"},"id":"shp_c614254e495246b18eafdfd19495405e","insurance":null,"is_return":false,"messages":[{"carrier":"DhlEcs","carrier_account_id":"ca_1fefcb0d0a9f4e5db5e5a1c360958484","message":"Unauthorized. - Please check credentials and try again","type":"rate_error"}],"mode":"test","object":"Shipment","options":{"currency":"USD","date_advance":0,"payment":{"type":"SENDER"}},"order_id":null,"parcel":{"created_at":"2023-11-30T20:11:57Z","height":4,"id":"prcl_93380daa897541809c2d49ec9019c12d","length":10,"mode":"test","object":"Parcel","predefined_package":null,"updated_at":"2023-11-30T20:11:57Z","weight":15.4,"width":8},"postage_label":null,"rates":[{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:57Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_d8444edf4cb1465491c119854b3c93a8","list_currency":"USD","list_rate":"8.24","mode":"test","object":"Rate","rate":"6.95","retail_currency":"USD","retail_rate":"10.20","service":"Priority","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:57Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_6c8fbaede5c74cd7a3e086f3f85be690","list_currency":"USD","list_rate":"6.07","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.00","service":"GroundAdvantage","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_50b9b8ea698f4e689069340edbd1b3b6","list_currency":"USD","list_rate":"6.07","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.00","service":"First","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_a5e18314b66f4587b824334d79888940","list_currency":"USD","list_rate":"6.07","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.00","service":"ParcelSelect","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":null,"est_delivery_days":null,"id":"rate_51cdf427f09d46c3bdb5dcb8e8c2bb07","list_currency":"USD","list_rate":"31.25","mode":"test","object":"Rate","rate":"31.25","retail_currency":"USD","retail_rate":"35.80","service":"Express","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"}],"reference":null,"refund_status":null,"return_address":{"carrier_facility":null,"city":"San - Francisco","company":null,"country":"US","created_at":"2023-11-30T20:11:57+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_b6925f748fbc11ee830cac1f6bc53342","mode":"test","name":"Jack + Townsend St","street2":"Apt 20","updated_at":"2024-07-12T19:41:46+00:00","verifications":{},"zip":"94107"},"id":"shp_5978035d160544d3983a9835d42a4ced","insurance":null,"is_return":false,"messages":[{"carrier":"DhlEcs","carrier_account_id":"ca_1fefcb0d0a9f4e5db5e5a1c360958484","message":"Invalid + credentials","type":"rate_error"}],"mode":"test","object":"Shipment","options":{"currency":"USD","date_advance":0,"payment":{"type":"SENDER"}},"order_id":null,"parcel":{"created_at":"2024-07-12T19:41:46Z","height":4,"id":"prcl_f0d7044d20d547b0a91a58fbce684a1b","length":10,"mode":"test","object":"Parcel","predefined_package":null,"updated_at":"2024-07-12T19:41:46Z","weight":15.4,"width":8},"postage_label":null,"rates":[{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_db43749a8e114a72b0408297c16d7149","list_currency":"USD","list_rate":"8.25","mode":"test","object":"Rate","rate":"6.90","retail_currency":"USD","retail_rate":"9.80","service":"Priority","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_a21ffd7919c04804b2649c55b81e8cbd","list_currency":"USD","list_rate":"6.40","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.45","service":"GroundAdvantage","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_8149f1a28f424582acfb11b935d15764","list_currency":"USD","list_rate":"6.40","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.45","service":"First","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_db823072aca84a7981bdca2d077ca02b","list_currency":"USD","list_rate":"6.40","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.45","service":"ParcelSelect","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_ce7738c350fa427aa6f6c12c3ca95eef","list_currency":"USD","list_rate":"33.10","mode":"test","object":"Rate","rate":"33.10","retail_currency":"USD","retail_rate":"37.90","service":"Express","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}],"reference":null,"refund_status":null,"return_address":{"carrier_facility":null,"city":"San + Francisco","company":null,"country":"US","created_at":"2024-07-12T19:41:46+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_c63a4efb408611efb412ac1f6bc539aa","mode":"test","name":"Jack Sparrow","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"388 - Townsend St","street2":"Apt 20","updated_at":"2023-11-30T20:11:57+00:00","verifications":{},"zip":"94107"},"scan_form":null,"selected_rate":null,"status":"unknown","to_address":{"carrier_facility":null,"city":"Redondo - Beach","company":null,"country":"US","created_at":"2023-11-30T20:11:57+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_b68ff41e8fbc11ee91adac1f6bc539aa","mode":"test","name":"Elizabeth + Townsend St","street2":"Apt 20","updated_at":"2024-07-12T19:41:46+00:00","verifications":{},"zip":"94107"},"scan_form":null,"selected_rate":null,"status":"unknown","to_address":{"carrier_facility":null,"city":"Redondo + Beach","company":null,"country":"US","created_at":"2024-07-12T19:41:46+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_c637342c408611ef87f33cecef1b359e","mode":"test","name":"Elizabeth Swan","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"179 - N Harbor Dr","street2":null,"updated_at":"2023-11-30T20:11:57+00:00","verifications":{},"zip":"90277"},"tracker":null,"tracking_code":null,"updated_at":"2023-11-30T20:11:58Z","usps_zone":4}' + N Harbor Dr","street2":null,"updated_at":"2024-07-12T19:41:46+00:00","verifications":{},"zip":"90277"},"tracker":null,"tracking_code":null,"updated_at":"2024-07-12T19:41:47Z","usps_zone":4}' headers: Cache-Control: - private, no-cache, no-store @@ -40,7 +40,7 @@ interactions: Expires: - "0" Location: - - /api/v2/shipments/shp_c614254e495246b18eafdfd19495405e + - /api/v2/shipments/shp_5978035d160544d3983a9835d42a4ced Pragma: - no-cache Referrer-Policy: @@ -54,27 +54,27 @@ interactions: X-Download-Options: - noopen X-Ep-Request-Uuid: - - 32e015fa6568ec8de7896122001b8fe6 + - d02331cd669186faf021797a00135240 X-Frame-Options: - SAMEORIGIN X-Node: - - bigweb36nuq + - bigweb38nuq X-Permitted-Cross-Domain-Policies: - none X-Proxied: - - intlb2nuq b3de2c47ef - - extlb1nuq 003ad9bca0 + - intlb4nuq fa152d4755 + - extlb1nuq fa152d4755 X-Runtime: - - "0.648742" + - "0.606831" X-Version-Label: - - easypost-202311301748-2efb918c5f-master + - easypost-202407121702-a82cfb9ac3-master X-Xss-Protection: - 1; mode=block status: 201 Created code: 201 duration: "" - request: - body: planned_ship_date=2023-12-28 + body: planned_ship_date=2024-07-17 form: {} headers: Authorization: @@ -83,10 +83,10 @@ interactions: - application/x-www-form-urlencoded User-Agent: - REDACTED - url: https://api.easypost.com/v2/shipments/shp_c614254e495246b18eafdfd19495405e/smartrate/delivery_date + url: https://api.easypost.com/v2/shipments/shp_5978035d160544d3983a9835d42a4ced/smartrate/delivery_date method: GET response: - body: '{"rates":[{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":5,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2023-12-30","planned_ship_date":"2023-12-28"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:57Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_d8444edf4cb1465491c119854b3c93a8","list_currency":"USD","list_rate":8.24,"mode":"test","object":"Rate","rate":6.95,"retail_currency":"USD","retail_rate":10.2,"service":"Priority","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:57Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":5,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2023-12-30","planned_ship_date":"2023-12-28"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_6c8fbaede5c74cd7a3e086f3f85be690","list_currency":"USD","list_rate":6.07,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8,"service":"GroundAdvantage","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":5,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2023-12-30","planned_ship_date":"2023-12-28"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_50b9b8ea698f4e689069340edbd1b3b6","list_currency":"USD","list_rate":6.07,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8,"service":"First","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":5,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2023-12-30","planned_ship_date":"2023-12-28"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_a5e18314b66f4587b824334d79888940","list_currency":"USD","list_rate":6.07,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8,"service":"ParcelSelect","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":1,"percentile_75":2,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2023-12-29","planned_ship_date":"2023-12-28"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2023-11-30T20:11:58Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":null,"est_delivery_days":null,"id":"rate_51cdf427f09d46c3bdb5dcb8e8c2bb07","list_currency":"USD","list_rate":31.25,"mode":"test","object":"Rate","rate":31.25,"retail_currency":"USD","retail_rate":35.8,"service":"Express","shipment_id":"shp_c614254e495246b18eafdfd19495405e","updated_at":"2023-11-30T20:11:58Z"}}]}' + body: '{"rates":[{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":8},"easypost_estimated_delivery_date":"2024-07-19","planned_ship_date":"2024-07-17"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_db43749a8e114a72b0408297c16d7149","list_currency":"USD","list_rate":8.25,"mode":"test","object":"Rate","rate":6.9,"retail_currency":"USD","retail_rate":9.8,"service":"Priority","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":9},"easypost_estimated_delivery_date":"2024-07-19","planned_ship_date":"2024-07-17"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_a21ffd7919c04804b2649c55b81e8cbd","list_currency":"USD","list_rate":6.4,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8.45,"service":"GroundAdvantage","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":9},"easypost_estimated_delivery_date":"2024-07-19","planned_ship_date":"2024-07-17"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_8149f1a28f424582acfb11b935d15764","list_currency":"USD","list_rate":6.4,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8.45,"service":"First","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":5,"percentile_90":5,"percentile_95":5,"percentile_97":6,"percentile_99":9},"easypost_estimated_delivery_date":"2024-07-19","planned_ship_date":"2024-07-17"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_db823072aca84a7981bdca2d077ca02b","list_currency":"USD","list_rate":6.4,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8.45,"service":"ParcelSelect","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":1,"percentile_75":2,"percentile_85":2,"percentile_90":3,"percentile_95":5,"percentile_97":5,"percentile_99":7},"easypost_estimated_delivery_date":"2024-07-18","planned_ship_date":"2024-07-17"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-12T19:41:47Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_ce7738c350fa427aa6f6c12c3ca95eef","list_currency":"USD","list_rate":33.1,"mode":"test","object":"Rate","rate":33.1,"retail_currency":"USD","retail_rate":37.9,"service":"Express","shipment_id":"shp_5978035d160544d3983a9835d42a4ced","updated_at":"2024-07-12T19:41:47Z"}}]}' headers: Cache-Control: - private, no-cache, no-store @@ -102,25 +102,27 @@ interactions: - max-age=31536000; includeSubDomains; preload X-Backend: - easypost + X-Canary: + - direct X-Content-Type-Options: - nosniff X-Download-Options: - noopen X-Ep-Request-Uuid: - - 32e015fa6568ec8ee7896122001b90f0 + - d02331cd669186fbf021797a001352c8 X-Frame-Options: - SAMEORIGIN X-Node: - - bigweb40nuq + - bigweb43nuq X-Permitted-Cross-Domain-Policies: - none X-Proxied: - - intlb1nuq b3de2c47ef - - extlb1nuq 003ad9bca0 + - intlb3nuq fa152d4755 + - extlb1nuq fa152d4755 X-Runtime: - - "0.112504" + - "0.126010" X-Version-Label: - - easypost-202311301748-2efb918c5f-master + - easypost-202407121702-a82cfb9ac3-master X-Xss-Protection: - 1; mode=block status: 200 OK diff --git a/tests/cassettes/TestShipmentRecommendShipDate.yaml b/tests/cassettes/TestShipmentRecommendShipDate.yaml new file mode 100644 index 0000000..d56df77 --- /dev/null +++ b/tests/cassettes/TestShipmentRecommendShipDate.yaml @@ -0,0 +1,130 @@ +--- +version: 1 +interactions: +- request: + body: '{"shipment":{"from_address":{"city":"San Francisco","country":"US","email":"REDACTED","name":"Jack + Sparrow","phone":"REDACTED","state":"CA","street1":"388 Townsend St","street2":"Apt + 20","zip":"94107"},"parcel":{"height":4,"length":10,"weight":15.4,"width":8},"to_address":{"city":"Redondo + Beach","country":"US","email":"REDACTED","name":"Elizabeth Swan","phone":"REDACTED","state":"CA","street1":"179 + N Harbor Dr","zip":"90277"}}}' + form: {} + headers: + Authorization: + - REDACTED + Content-Type: + - application/json + User-Agent: + - REDACTED + url: https://api.easypost.com/v2/shipments + method: POST + response: + body: '{"batch_id":null,"batch_message":null,"batch_status":null,"buyer_address":{"carrier_facility":null,"city":"Redondo + Beach","company":null,"country":"US","created_at":"2024-07-15T23:39:25+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_78894293430311ef9ec0ac1f6bc539aa","mode":"test","name":"Elizabeth + Swan","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"179 + N Harbor Dr","street2":null,"updated_at":"2024-07-15T23:39:25+00:00","verifications":{},"zip":"90277"},"created_at":"2024-07-15T23:39:25Z","customs_info":null,"fees":[],"forms":[],"from_address":{"carrier_facility":null,"city":"San + Francisco","company":null,"country":"US","created_at":"2024-07-15T23:39:25+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_788bfce3430311ef9b33ac1f6bc53342","mode":"test","name":"Jack + Sparrow","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"388 + Townsend St","street2":"Apt 20","updated_at":"2024-07-15T23:39:25+00:00","verifications":{},"zip":"94107"},"id":"shp_0921d00a5f254354a9d9d2893962b19c","insurance":null,"is_return":false,"messages":[{"carrier":"DhlEcs","carrier_account_id":"ca_1fefcb0d0a9f4e5db5e5a1c360958484","message":"Invalid + credentials","type":"rate_error"}],"mode":"test","object":"Shipment","options":{"currency":"USD","date_advance":0,"payment":{"type":"SENDER"}},"order_id":null,"parcel":{"created_at":"2024-07-15T23:39:25Z","height":4,"id":"prcl_9f805bea2b1440499633960eecd63fd8","length":10,"mode":"test","object":"Parcel","predefined_package":null,"updated_at":"2024-07-15T23:39:25Z","weight":15.4,"width":8},"postage_label":null,"rates":[{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_b57b0e7c1a304262acf1eada74966061","list_currency":"USD","list_rate":"33.10","mode":"test","object":"Rate","rate":"33.10","retail_currency":"USD","retail_rate":"37.90","service":"Express","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_aacbefa7901e4ba48ab0f3c19e80619d","list_currency":"USD","list_rate":"8.25","mode":"test","object":"Rate","rate":"6.90","retail_currency":"USD","retail_rate":"9.80","service":"Priority","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"},{"billing_type":"easypost","carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_dce19b666af24c0994e4bfa1156acd09","list_currency":"USD","list_rate":"6.40","mode":"test","object":"Rate","rate":"5.93","retail_currency":"USD","retail_rate":"8.45","service":"GroundAdvantage","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"}],"reference":null,"refund_status":null,"return_address":{"carrier_facility":null,"city":"San + Francisco","company":null,"country":"US","created_at":"2024-07-15T23:39:25+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_788bfce3430311ef9b33ac1f6bc53342","mode":"test","name":"Jack + Sparrow","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"388 + Townsend St","street2":"Apt 20","updated_at":"2024-07-15T23:39:25+00:00","verifications":{},"zip":"94107"},"scan_form":null,"selected_rate":null,"status":"unknown","to_address":{"carrier_facility":null,"city":"Redondo + Beach","company":null,"country":"US","created_at":"2024-07-15T23:39:25+00:00","email":"REDACTED","federal_tax_id":null,"id":"adr_78894293430311ef9ec0ac1f6bc539aa","mode":"test","name":"Elizabeth + Swan","object":"Address","phone":"REDACTED","residential":null,"state":"CA","state_tax_id":null,"street1":"179 + N Harbor Dr","street2":null,"updated_at":"2024-07-15T23:39:25+00:00","verifications":{},"zip":"90277"},"tracker":null,"tracking_code":null,"updated_at":"2024-07-15T23:39:26Z","usps_zone":4}' + headers: + Cache-Control: + - private, no-cache, no-store + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Location: + - /api/v2/shipments/shp_0921d00a5f254354a9d9d2893962b19c + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + X-Backend: + - easypost + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Ep-Request-Uuid: + - 52dadcf36695b32df4084f0b004b67fb + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb53nuq + X-Permitted-Cross-Domain-Policies: + - none + X-Proxied: + - intlb4nuq fa152d4755 + - extlb1nuq fa152d4755 + X-Runtime: + - "0.570346" + X-Version-Label: + - easypost-202407152305-b86700bd54-master + X-Xss-Protection: + - 1; mode=block + status: 201 Created + code: 201 + duration: "" +- request: + body: desired_delivery_date=2024-07-17 + form: {} + headers: + Authorization: + - REDACTED + Content-Type: + - application/x-www-form-urlencoded + User-Agent: + - REDACTED + url: https://api.easypost.com/v2/shipments/shp_0921d00a5f254354a9d9d2893962b19c/smartrate/precision_shipping + method: GET + response: + body: '{"rates":[{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":2,"percentile_75":2,"percentile_85":3,"percentile_90":3,"percentile_95":4,"percentile_97":4,"percentile_99":6},"delivery_date_confidence":0.46,"desired_delivery_date":"2024-07-17","estimated_transit_days":1,"ship_on_date":"2024-07-16"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_b57b0e7c1a304262acf1eada74966061","list_currency":"USD","list_rate":33.1,"mode":"test","object":"Rate","rate":33.1,"retail_currency":"USD","retail_rate":37.9,"service":"Express","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":4,"percentile_90":4,"percentile_95":5,"percentile_97":7,"percentile_99":8},"delivery_date_confidence":0.31,"desired_delivery_date":"2024-07-17","estimated_transit_days":2,"ship_on_date":"2024-07-15"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":2,"est_delivery_days":2,"id":"rate_aacbefa7901e4ba48ab0f3c19e80619d","list_currency":"USD","list_rate":8.25,"mode":"test","object":"Rate","rate":6.9,"retail_currency":"USD","retail_rate":9.8,"service":"Priority","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"}},{"easypost_time_in_transit_data":{"days_in_transit":{"percentile_50":3,"percentile_75":3,"percentile_85":4,"percentile_90":4,"percentile_95":5,"percentile_97":7,"percentile_99":8},"delivery_date_confidence":0.32,"desired_delivery_date":"2024-07-17","estimated_transit_days":2,"ship_on_date":"2024-07-15"},"rate":{"carrier":"USPS","carrier_account_id":"ca_e606176ddb314afe896733636dba2f3b","created_at":"2024-07-15T23:39:26Z","currency":"USD","delivery_date":null,"delivery_date_guaranteed":false,"delivery_days":3,"est_delivery_days":3,"id":"rate_dce19b666af24c0994e4bfa1156acd09","list_currency":"USD","list_rate":6.4,"mode":"test","object":"Rate","rate":5.93,"retail_currency":"USD","retail_rate":8.45,"service":"GroundAdvantage","shipment_id":"shp_0921d00a5f254354a9d9d2893962b19c","updated_at":"2024-07-15T23:39:26Z"}}]}' + headers: + Cache-Control: + - private, no-cache, no-store + Content-Type: + - application/json; charset=utf-8 + Expires: + - "0" + Pragma: + - no-cache + Referrer-Policy: + - strict-origin-when-cross-origin + Strict-Transport-Security: + - max-age=31536000; includeSubDomains; preload + X-Backend: + - easypost + X-Canary: + - direct + X-Content-Type-Options: + - nosniff + X-Download-Options: + - noopen + X-Ep-Request-Uuid: + - 52dadcf36695b32ef4084f0b004b687a + X-Frame-Options: + - SAMEORIGIN + X-Node: + - bigweb32nuq + X-Permitted-Cross-Domain-Policies: + - none + X-Proxied: + - intlb3nuq fa152d4755 + - extlb1nuq fa152d4755 + X-Runtime: + - "0.119930" + X-Version-Label: + - easypost-202407152305-b86700bd54-master + X-Xss-Protection: + - 1; mode=block + status: 200 OK + code: 200 + duration: "" diff --git a/tests/fixture_test.go b/tests/fixture_test.go index 6da9405..eae0ba9 100644 --- a/tests/fixture_test.go +++ b/tests/fixture_test.go @@ -218,5 +218,9 @@ func (fixture *Fixture) TestCreditCard() *easypost.CreditCardOptions { } func (fixture *Fixture) PlannedShipDate() string { - return "2023-12-28" + return "2024-07-17" +} + +func (fixture *Fixture) DesiredDeliveryDate() string { + return "2024-07-17" } diff --git a/tests/shipment_test.go b/tests/shipment_test.go index 6a5d84f..346149c 100644 --- a/tests/shipment_test.go +++ b/tests/shipment_test.go @@ -353,10 +353,33 @@ func (c *ClientTests) TestShipmentGetShipmentEstimatedDeliveryDate() { shipment, err := client.CreateShipment(c.fixture.BasicShipment()) require.NoError(err) - rates, err := client.GetShipmentEstimatedDeliveryDate(shipment.ID, c.fixture.PlannedShipDate()) + estimates, err := client.GetShipmentEstimatedDeliveryDate(shipment.ID, c.fixture.PlannedShipDate()) require.NoError(err) - for _, entry := range rates { - assert.NotNil(entry.EasyPostTimeInTransitData) + assert.True(len(estimates) > 0) + for _, entry := range estimates { + assert.NotNil(entry.EasyPostTimeInTransitData.EasyPostEstimatedDeliveryDate) + assert.NotNil(entry.EasyPostTimeInTransitData.DaysInTransit) + assert.NotNil(entry.EasyPostTimeInTransitData.PlannedShipDate) + } +} + +func (c *ClientTests) TestShipmentRecommendShipDate() { + client := c.TestClient() + assert, require := c.Assert(), c.Require() + + shipment, err := client.CreateShipment(c.fixture.BasicShipment()) + require.NoError(err) + + recommendations, err := client.RecommendShipDateForShipment(shipment.ID, c.fixture.DesiredDeliveryDate()) + require.NoError(err) + + assert.True(len(recommendations) > 0) + for _, entry := range recommendations { + assert.NotNil(entry.EasyPostTimeInTransitData.EasyPostRecommendedShipDate) + assert.NotNil(entry.EasyPostTimeInTransitData.DeliveryDateConfidence) + assert.NotNil(entry.EasyPostTimeInTransitData.EstimatedTransitDays) + assert.NotNil(entry.EasyPostTimeInTransitData.DaysInTransit) + assert.NotNil(entry.EasyPostTimeInTransitData.DesiredDeliveryDate) } } diff --git a/tests/smart_rate_test.go b/tests/smart_rate_test.go new file mode 100644 index 0000000..10b6414 --- /dev/null +++ b/tests/smart_rate_test.go @@ -0,0 +1,62 @@ +package easypost_test + +import ( + "github.com/EasyPost/easypost-go/v4" +) + +func (c *ClientTests) TestEstimateDeliveryDateForZipPair() { + client := c.TestClient() + assert, require := c.Assert(), c.Require() + + carrier := c.fixture.USPS() + + params := &easypost.EstimateDeliveryDateForZipPairParams{ + FromZip: c.fixture.CaAddress1().Zip, + ToZip: c.fixture.CaAddress2().Zip, + Carriers: []string{carrier}, + PlannedShipDate: c.fixture.PlannedShipDate(), + } + + estimates, err := client.EstimateDeliveryDateForZipPair(params) + require.NoError(err) + + assert.Equal(estimates.FromZip, params.FromZip) + assert.Equal(estimates.ToZip, params.ToZip) + assert.True(len(estimates.Results) > 0) + for _, entry := range estimates.Results { + assert.NotNil(entry.Carrier) + assert.NotNil(entry.Service) + assert.NotNil(entry.EasyPostTimeInTransitData.EasyPostEstimatedDeliveryDate) + assert.NotNil(entry.EasyPostTimeInTransitData.DaysInTransit) + } +} + +func (c *ClientTests) TestRecommendShipDateForZipPair() { + client := c.TestClient() + assert, require := c.Assert(), c.Require() + + carrier := c.fixture.USPS() + + params := &easypost.RecommendShipDateForZipPairParams{ + FromZip: c.fixture.CaAddress1().Zip, + ToZip: c.fixture.CaAddress2().Zip, + Carriers: []string{carrier}, + DesiredDeliveryDate: c.fixture.DesiredDeliveryDate(), + } + + recommendations, err := client.RecommendShipDateForZipPair(params) + require.NoError(err) + + assert.Equal(recommendations.FromZip, params.FromZip) + assert.Equal(recommendations.ToZip, params.ToZip) + assert.True(len(recommendations.Results) > 0) + for _, entry := range recommendations.Results { + assert.NotNil(entry.Carrier) + assert.NotNil(entry.Service) + assert.NotNil(entry.EasyPostTimeInTransitData.EasyPostRecommendedShipDate) + assert.NotNil(entry.EasyPostTimeInTransitData.DaysInTransit) + assert.NotNil(entry.EasyPostTimeInTransitData.DeliveryDateConfidence) + assert.NotNil(entry.EasyPostTimeInTransitData.EstimatedTransitDays) + } + +}