From e251fd11c2bd28c4f45c78961ccbcadebe72bba5 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 30 May 2023 14:58:47 +0200 Subject: [PATCH 1/4] Added Locations to create a location within the shop using the API --- locations.go | 144 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 144 insertions(+) create mode 100644 locations.go diff --git a/locations.go b/locations.go new file mode 100644 index 0000000..58e3354 --- /dev/null +++ b/locations.go @@ -0,0 +1,144 @@ +package bigcommerce + +import ( + "bytes" + "encoding/json" + "fmt" + "net/http" + "strings" +) + +type Location struct { + Code string `json:"code"` + Label string `json:"label"` + Description string `json:"description"` + ManagedByExternalSource bool `json:"managed_by_external_source"` + TypeId string `json:"type_id"` + Enabled bool `json:"enabled"` + OperatingHours LocationOpeningHours `json:"operating_hours"` + TimeZone string `json:"time_zone"` + Address LocationAddress `json:"address"` + StorefrontVisibility bool `json:"storefront_visibility"` + SpecialHours []LocationSpecialHours `json:"special_hours"` +} + +type LocationAddress struct { + Address1 string `json:"address1"` + Address2 string `json:"address2"` + City string `json:"city"` + State string `json:"state"` + Zip string `json:"zip"` + Email string `json:"email"` + Phone string `json:"phone"` + GeoCoordinates struct { + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` + } `json:"geo_coordinates"` + CountryCode string `json:"country_code"` +} + +type LocationOpeningHours struct { + Sunday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"sunday"` + Monday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"monday"` + Tuesday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"tuesday"` + Wednesday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"wednesday"` + Thursday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"thursday"` + Friday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"friday"` + Saturday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + } `json:"saturday"` +} + +type LocationSpecialHours struct { + Label string `json:"label"` + Date string `json:"date"` + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` + AllDay bool `json:"all_day"` + Annual bool `json:"annual"` +} + +// GetLocations returns all orders using filters. +// filters: request query parameters for BigCommerce locations endpoint, for example {"is_active": true} +func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) { + var params []string + for k, v := range filters { + params = append(params, fmt.Sprintf("%s=%s", k, v)) + } + url := "/v3/inventory/locations?" + strings.Join(params, "&") + + req := bc.getAPIRequest(http.MethodGet, url, nil) + res, err := bc.HTTPClient.Do(req) + if err != nil { + return nil, err + } + + defer res.Body.Close() + body, err := processBody(res) + if err != nil { + if res.StatusCode == http.StatusNoContent { + return []Location{}, nil + } + return nil, err + } + + var locations []Location + err = json.Unmarshal(body, &locations) + if err != nil { + return nil, err + } + return locations, nil +} + +func (bc *Client) CreateLocation(location *Location) error { + url := "/v3/inventory/locations" + + reqJSON, _ := json.Marshal(location) + req := bc.getAPIRequest(http.MethodPost, url, bytes.NewReader(reqJSON)) + _, err := bc.HTTPClient.Do(req) + if err != nil { + return err + } + + return nil +} + +func (bc *Client) UpdateLocation(location *Location) error { + url := "/v3/inventory/locations" + + reqJSON, _ := json.Marshal(location) + req := bc.getAPIRequest(http.MethodPut, url, bytes.NewReader(reqJSON)) + _, err := bc.HTTPClient.Do(req) + if err != nil { + return err + } + + return nil +} From 6c53b4f77ae7dea0e9140f4f538a2ebd9034640d Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 30 May 2023 14:59:05 +0200 Subject: [PATCH 2/4] Added Adjustments to adjust the current stock within the shop --- adjustments.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 adjustments.go diff --git a/adjustments.go b/adjustments.go new file mode 100644 index 0000000..adeee25 --- /dev/null +++ b/adjustments.go @@ -0,0 +1,46 @@ +package bigcommerce + +import ( + "bytes" + "encoding/json" + "net/http" +) + +type Adjustment struct { + Reason string `json:"reason"` + Items []Item `json:"items"` +} + +type Item struct { + LocationId int `json:"location_id"` + VariantId int `json:"variant_id,omitempty"` + Quantity int `json:"quantity"` + Sku string `json:"sku,omitempty"` + ProductId int `json:"product_id,omitempty"` +} + +func (bc *Client) AdjustInventoryRelative(adjustment *Adjustment) error { + url := "/v3/inventory/adjustments/relative" + + reqJSON, _ := json.Marshal(adjustment) + req := bc.getAPIRequest(http.MethodPost, url, bytes.NewReader(reqJSON)) + _, err := bc.HTTPClient.Do(req) + if err != nil { + return err + } + + return nil +} + +func (bc *Client) AdjustInventoryAbsolute(adjustment *Adjustment) error { + url := "/v3/inventory/adjustments/absolute" + + reqJSON, _ := json.Marshal(adjustment) + req := bc.getAPIRequest(http.MethodPost, url, bytes.NewReader(reqJSON)) + _, err := bc.HTTPClient.Do(req) + if err != nil { + return err + } + + return nil +} From eb68abc906db0d3c8c7d0049de2ffc0da4a8c8d8 Mon Sep 17 00:00:00 2001 From: Tim Date: Tue, 30 May 2023 15:10:32 +0200 Subject: [PATCH 3/4] Added documentation --- README.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++ adjustments.go | 8 +++--- locations.go | 4 ++- 3 files changed, 74 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index ac6d02b..428a8b2 100644 --- a/README.md +++ b/README.md @@ -1902,3 +1902,69 @@ GetWebhookPayload returns a WebhookPayload object and the raw payload from the BigCommerce API Arguments: r - the http.Request object Returns: *WebhookPayload - the WebhookPayload object []byte - the raw payload from the BigCommerce API error - the error, if any + +#### type Adjustment +```go +type Adjustment struct { + Reason string `json:"reason"` + Items []AdjustmentItem `json:"items"` +} +``` + +#### type AdjustmentItem +```go +type AdjustmentItem struct { + LocationId int `json:"location_id"` + VariantId int `json:"variant_id,omitempty"` + Quantity int `json:"quantity"` + Sku string `json:"sku,omitempty"` + ProductId int `json:"product_id,omitempty"` +} +``` + +#### func AdjustInventoryRelative +```go +func (bc *Client) AdjustInventoryRelative(adjustment *Adjustment) error +``` +Adjusts the inventory relatively to it's current value. -1 will subtract one, and 1 will add one to the stock. + +#### func AdjustInventoryAbsolute +```go +func (bc *Client) AdjustInventoryAbsolute(adjustment *Adjustment) error +``` +Set the inventory's stock value absolutely to the value given. -1 will set the value to -1, 1 will set it to 1. + +#### type Location +```go +type Location struct { + Code string `json:"code"` + Label string `json:"label"` + Description string `json:"description"` + ManagedByExternalSource bool `json:"managed_by_external_source"` + TypeId string `json:"type_id"` + Enabled bool `json:"enabled"` + OperatingHours LocationOpeningHours `json:"operating_hours"` + TimeZone string `json:"time_zone"` + Address LocationAddress `json:"address"` + StorefrontVisibility bool `json:"storefront_visibility"` + SpecialHours []LocationSpecialHours `json:"special_hours"` +} +``` + +#### func GetLocations +```go +func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) +``` +Gets all the locations that belong to a shop + +#### func CreateLocation +```go +func (bc *Client) CreateLocation(location *Location) error +``` +Create a new location + +#### func UpdateLocation +```go +func (bc *Client) UpdateLocation(location *Location) error +``` +Updates the locations values \ No newline at end of file diff --git a/adjustments.go b/adjustments.go index adeee25..a2bbb46 100644 --- a/adjustments.go +++ b/adjustments.go @@ -7,11 +7,11 @@ import ( ) type Adjustment struct { - Reason string `json:"reason"` - Items []Item `json:"items"` + Reason string `json:"reason"` + Items []AdjustmentItem `json:"items"` } -type Item struct { +type AdjustmentItem struct { LocationId int `json:"location_id"` VariantId int `json:"variant_id,omitempty"` Quantity int `json:"quantity"` @@ -19,6 +19,7 @@ type Item struct { ProductId int `json:"product_id,omitempty"` } +// AdjustInventoryRelative changes the stock value relative to it's current value func (bc *Client) AdjustInventoryRelative(adjustment *Adjustment) error { url := "/v3/inventory/adjustments/relative" @@ -32,6 +33,7 @@ func (bc *Client) AdjustInventoryRelative(adjustment *Adjustment) error { return nil } +// AdjustInventoryAbsolute sets the stock value to a specific value func (bc *Client) AdjustInventoryAbsolute(adjustment *Adjustment) error { url := "/v3/inventory/adjustments/absolute" diff --git a/locations.go b/locations.go index 58e3354..c92496e 100644 --- a/locations.go +++ b/locations.go @@ -85,7 +85,7 @@ type LocationSpecialHours struct { Annual bool `json:"annual"` } -// GetLocations returns all orders using filters. +// GetLocations returns all locations using filters. // filters: request query parameters for BigCommerce locations endpoint, for example {"is_active": true} func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) { var params []string @@ -117,6 +117,7 @@ func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) { return locations, nil } +// CreateLocation creates a new location based on the Location struct func (bc *Client) CreateLocation(location *Location) error { url := "/v3/inventory/locations" @@ -130,6 +131,7 @@ func (bc *Client) CreateLocation(location *Location) error { return nil } +// UpdateLocation alters the locations values func (bc *Client) UpdateLocation(location *Location) error { url := "/v3/inventory/locations" From 318ec1dedc07e0eccd73a93a1ccce3ac937adeab Mon Sep 17 00:00:00 2001 From: Tim Date: Wed, 31 May 2023 15:04:27 +0200 Subject: [PATCH 4/4] Creating locations will now accept an array of locations instead of one, allowing it to work --- locations.go | 90 +++++++++++++++++++++++----------------------------- 1 file changed, 39 insertions(+), 51 deletions(-) diff --git a/locations.go b/locations.go index c92496e..f9e3a8e 100644 --- a/locations.go +++ b/locations.go @@ -3,6 +3,7 @@ package bigcommerce import ( "bytes" "encoding/json" + "errors" "fmt" "net/http" "strings" @@ -19,60 +20,34 @@ type Location struct { TimeZone string `json:"time_zone"` Address LocationAddress `json:"address"` StorefrontVisibility bool `json:"storefront_visibility"` - SpecialHours []LocationSpecialHours `json:"special_hours"` + SpecialHours []LocationSpecialHours `json:"special_hours,omitempty"` } type LocationAddress struct { - Address1 string `json:"address1"` - Address2 string `json:"address2"` - City string `json:"city"` - State string `json:"state"` - Zip string `json:"zip"` - Email string `json:"email"` - Phone string `json:"phone"` - GeoCoordinates struct { - Latitude float64 `json:"latitude"` - Longitude float64 `json:"longitude"` - } `json:"geo_coordinates"` - CountryCode string `json:"country_code"` + Address1 string `json:"address1"` + Address2 string `json:"address2"` + City string `json:"city"` + State string `json:"state"` + Zip string `json:"zip"` + Email string `json:"email"` + Phone string `json:"phone"` + GeoCoordinates Coordenates `json:"geo_coordinates"` + CountryCode string `json:"country_code"` +} + +type Coordenates struct { + Latitude float64 `json:"latitude"` + Longitude float64 `json:"longitude"` } type LocationOpeningHours struct { - Sunday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"sunday"` - Monday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"monday"` - Tuesday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"tuesday"` - Wednesday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"wednesday"` - Thursday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"thursday"` - Friday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"friday"` - Saturday struct { - Open bool `json:"open"` - Opening string `json:"opening"` - Closing string `json:"closing"` - } `json:"saturday"` + Sunday Weekday `json:"sunday"` + Monday Weekday `json:"monday"` + Tuesday Weekday `json:"tuesday"` + Wednesday Weekday `json:"wednesday"` + Thursday Weekday `json:"thursday"` + Friday Weekday `json:"friday"` + Saturday Weekday `json:"saturday"` } type LocationSpecialHours struct { @@ -85,6 +60,12 @@ type LocationSpecialHours struct { Annual bool `json:"annual"` } +type Weekday struct { + Open bool `json:"open"` + Opening string `json:"opening"` + Closing string `json:"closing"` +} + // GetLocations returns all locations using filters. // filters: request query parameters for BigCommerce locations endpoint, for example {"is_active": true} func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) { @@ -111,23 +92,30 @@ func (bc *Client) GetLocations(filters map[string]string) ([]Location, error) { var locations []Location err = json.Unmarshal(body, &locations) + print(string(body)) if err != nil { return nil, err } return locations, nil } -// CreateLocation creates a new location based on the Location struct -func (bc *Client) CreateLocation(location *Location) error { +// CreateLocations creates a new location based on the Location struct +func (bc *Client) CreateLocations(location *[]Location) error { url := "/v3/inventory/locations" reqJSON, _ := json.Marshal(location) + + fmt.Println(string(reqJSON)) req := bc.getAPIRequest(http.MethodPost, url, bytes.NewReader(reqJSON)) - _, err := bc.HTTPClient.Do(req) + res, err := bc.HTTPClient.Do(req) if err != nil { return err } + if res.StatusCode != 200 { + return errors.New(res.Status) + } + return nil }