aboutsummaryrefslogtreecommitdiffstats
path: root/ship.go
diff options
context:
space:
mode:
Diffstat (limited to 'ship.go')
-rw-r--r--ship.go119
1 files changed, 109 insertions, 10 deletions
diff --git a/ship.go b/ship.go
index aef655e..b5aa822 100644
--- a/ship.go
+++ b/ship.go
@@ -1,6 +1,11 @@
package lulu
-//go:generate go run github.com/yawnak/string-enumer -t ShippingLevel --text -o ./ship_gen.go .
+import (
+ "encoding/json"
+ "fmt"
+)
+
+//go:generate go run github.com/yawnak/string-enumer -t ShippingLevel -t Title --text -o ./ship_gen.go .
// ShippingLevel is the quality/speed with which a package is shipped.
type ShippingLevel string
@@ -14,13 +19,107 @@ const (
)
type ShippingAddress struct {
- Name string `json:"name"`
- Phone string `json:"phone_number"`
- CountryCode string `json:"country_code"`
- PostCode string `json:"postcode"`
- StateCode string `json:"state_code"`
- City string `json:"city"`
- Street1 string `json:"street1"`
- Street2 string `json:"street2"`
- IsBusiness bool `json:"is_business"`
+ Country string // ISO 3166-2 country code
+ State string // 2 or 3 letter state codes (officially called ISO-3166-2 subdivision codes). They are required for some countries (e.g. US, MX, CA, AU)
+ City string
+ Street1 string // First address line
+ Street2 string // Second address line
+ PostCode string // Required for most countries
+ IsBusiness bool // Only relevant for US addresses. Some US carriers don't deliver to business-addresses on Saturday.
+ Name string // Full name of the person, including first and last name.
+ Title Title
+ Organization string // Name of an organization. Required if no person name is given.
+ Email string // Shipping carriers require an email address for notifications or handling delivery issues. If no email is given, the default email in the user profile will be used.
+ Phone string // Shipping carriers require a phone number for handling delivery issues. If no phone number is given, the default in the API user profile will be used.
+ TaxId string // The recipient’s tax identification number. Required for shipping addresses to Brazil, Chile, and Mexico.
+}
+
+// They use "country" in some places, "country_code" in others, etc.
+// This is the union of all of them.
+type shippingAddress struct {
+ Country string `json:"country"`
+ CountryCode string `json:"country_code"`
+ State string `json:"state"`
+ StateCode string `json:"state_code"`
+ City string `json:"city"`
+ Street1 string `json:"street1"`
+ Street2 string `json:"street2"`
+ PostCode string `json:"postcode"`
+ IsBusiness bool `json:"is_business"`
+ Name string `json:"name"`
+ FirstName string `json:"first_name"`
+ LastName string `json:"last_name"`
+ Title Title `json:"title"`
+ Organization string `json:"organization"`
+ Email string `json:"email"`
+ Phone string `json:"phone_number"`
+ TaxId string `json:"recipient_tax_id"`
+}
+
+func (a *ShippingAddress) UnmarshalJSON(data []byte) error {
+ s := string(data)
+ var alias shippingAddress
+ if err := json.Unmarshal(data, &alias); err != nil {
+ return err
+ }
+
+ if country, both := either(alias.Country, alias.CountryCode); !both {
+ a.Country = country
+ } else {
+ return fmt.Errorf(`address contains both "country" and "country_code": %q`, s)
+ }
+
+ if state, both := either(alias.State, alias.StateCode); !both {
+ a.State = state
+ } else {
+ return fmt.Errorf(`address contains both "state" and "state_code": %q`, s)
+ }
+
+ a.City = alias.City
+ a.Street1 = alias.Street1
+ a.Street2 = alias.Street2
+ a.PostCode = alias.PostCode
+ a.IsBusiness = alias.IsBusiness
+
+ hasName := alias.Name != ""
+ hasFirst := alias.FirstName != ""
+ hasLast := alias.LastName != ""
+ if hasName && (hasFirst || hasLast) {
+ return fmt.Errorf(`address contains both "name" and {"first_name", "last_name"}: %q`, s)
+ } else if hasName {
+ a.Name = alias.Name
+ } else if hasFirst && hasLast {
+ a.Name = fmt.Sprintf("%s %s", alias.FirstName, alias.LastName)
+ } else if hasLast {
+ a.Name = alias.LastName
+ } else if hasFirst {
+ a.Name = alias.FirstName
+ }
+
+ a.Title = alias.Title
+ a.Organization = alias.Organization
+ a.Email = alias.Email
+ a.Phone = alias.Phone
+ a.TaxId = alias.TaxId
+
+ return nil
+}
+
+func either(a, b string) (string, bool) {
+ if a != "" && b != "" {
+ return a, true
+ } else if a != "" {
+ return a, false
+ }
+ return b, false
}
+
+type Title string
+
+const (
+ Mr Title = "MR"
+ Miss Title = "MISS"
+ Mrs Title = "MRS"
+ Ms Title = "MS"
+ Dr Title = "DR"
+)