Compare commits

..

No commits in common. "master" and "v1.3.3" have entirely different histories.

36 changed files with 8414 additions and 15079 deletions

View file

@ -1,79 +0,0 @@
name: ci
on:
push:
branches:
- '**'
tags-ignore:
- '*.*'
pull_request:
env:
RETAILCRM_URL: https://test.retailcrm.pro
RETAILCRM_KEY: key
jobs:
golangci:
name: lint
if: ${{ github.event_name == 'pull_request' }}
runs-on: ubuntu-latest
steps:
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Set up Go 1.23
uses: actions/setup-go@v3
with:
go-version: '1.23'
- name: Get dependencies
run: |
go mod tidy
cp .env.dist .env
- name: Lint code with golangci-lint
uses: golangci/golangci-lint-action@v3
with:
version: v1.62.2
only-new-issues: true
skip-pkg-cache: true
args: --build-tags=testutils
tests:
name: Tests
runs-on: ubuntu-latest
strategy:
matrix:
go-version: ['1.19', '1.20', '1.21', '1.22', '1.23', 'stable']
include:
- go-version: '1.23'
coverage: 1
steps:
- name: Set up Go ${{ matrix.go-version }}
uses: actions/setup-go@v3
with:
go-version: ${{ matrix.go-version }}
- name: Check out code into the Go module directory
uses: actions/checkout@v2
- name: Get dependencies
run: |
go mod tidy
cp .env.dist .env
- name: Tests
env:
COVERAGE: ${{ matrix.coverage }}
if: env.COVERAGE != 1
run: |
go install gotest.tools/gotestsum@latest
gotestsum --format testdox ./... -tags=testutils -v -cpu 2 -timeout 60s -race
- name: Tests with coverage
env:
COVERAGE: ${{ matrix.coverage }}
if: env.COVERAGE == 1
run: |
go install gotest.tools/gotestsum@latest
gotestsum --format testdox ./... -tags=testutils -v -cpu 2 -timeout 60s -race -cover -coverprofile=coverage.txt -covermode=atomic "$d"
- name: Coverage
env:
COVERAGE: ${{ matrix.coverage }}
if: env.COVERAGE == 1
run: |
go install github.com/axw/gocov/gocov@latest
gocov convert ./coverage.txt | gocov report
bash <(curl -s https://codecov.io/bash)

1
.gitignore vendored
View file

@ -5,7 +5,6 @@
# Folders # Folders
_obj _obj
vendor
# Architecture specific extensions/prefixes # Architecture specific extensions/prefixes
*.[568vq] *.[568vq]

View file

@ -1,213 +0,0 @@
run:
skip-dirs-use-default: true
allow-parallel-runners: true
issues:
exclude-files:
- testutils.go
exclude-rules:
- path: _test\.go
linters:
- lll
- errcheck
- misspell
- ineffassign
- whitespace
- makezero
- errcheck
- funlen
- goconst
- gocognit
- gocyclo
- godot
- unused
- errchkjson
- varnamelen
exclude-use-default: true
exclude-case-sensitive: false
max-issues-per-linter: 0
max-same-issues: 0
fix: true
output:
formats:
- format: colored-line-number
sort-results: true
# Linters below do not support go1.18 yet because of generics.
# See https://github.com/golangci/golangci-lint/issues/2649
# - bodyclose
# - sqlclosecheck
linters:
disable-all: true
enable:
- asciicheck
- asasalint
- varnamelen
- reassign
- nilnil
- nilerr
- nakedret
- goprintffuncname
- typecheck
- errchkjson
- errcheck
- gosimple
- govet
- ineffassign
- staticcheck
- unused
- unparam
- dogsled
- dupl
- errorlint
- exhaustive
- exportloopref
- copyloopvar
- funlen
- gocognit
- goconst
- gocritic
- gocyclo
- godot
- goimports
- revive
- gosec
- lll
- makezero
- misspell
- nestif
- prealloc
- predeclared
- unconvert
- whitespace
linters-settings:
govet:
check-shadowing: false
disable-all: true
enable:
- assign
- atomic
- atomicalign
- bools
- buildtag
- copylocks
- httpresponse
- loopclosure
- lostcancel
- printf
- shift
- stdmethods
- structtag
- tests
- unmarshal
- unreachable
- unsafeptr
settings:
printf:
funcs:
- (*log.Logger).Fatal
- (*log.Logger).Fatalf
- (*log.Logger).Fatalln
- (*log.Logger).Panic
- (*log.Logger).Panicf
- (*log.Logger).Panicln
- (*log.Logger).Print
- (*log.Logger).Printf
- (*log.Logger).Println
- (*testing.common).Error
- (*testing.common).Errorf
- (*testing.common).Fatal
- (*testing.common).Fatalf
- (*testing.common).Log
- (*testing.common).Logf
- (*testing.common).Skip
- (*testing.common).Skipf
- (testing.TB).Error
- (testing.TB).Errorf
- (testing.TB).Fatal
- (testing.TB).Fatalf
- (testing.TB).Log
- (testing.TB).Logf
- (testing.TB).Skip
- (testing.TB).Skipf
- fmt.Errorf
- fmt.Fprint
- fmt.Fprintf
- fmt.Fprintln
- fmt.Print
- fmt.Printf
- fmt.Println
- fmt.Sprint
- fmt.Sprintf
- fmt.Sprintln
- log.Fatal
- log.Fatalf
- log.Fatalln
- log.Panic
- log.Panicf
- log.Panicln
- log.Print
- log.Printf
- log.Println
- runtime/trace.Logf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Fatalf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Panicf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Panicf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Criticalf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Errorf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Warningf
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Noticef
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Infof
- (github.com/retailcrm/mg-transport-core/core.LoggerInterface).Debugf
unused:
check-exported: false
unparam:
check-exported: false
dogsled:
max-blank-identifiers: 3
dupl:
threshold: 200
errorlint:
errorf: true
asserts: false
comparison: false
exhaustive:
check-generated: false
default-signifies-exhaustive: false
funlen:
lines: 90
statements: 40
gocognit:
min-complexity: 25
gocyclo:
min-complexity: 25
goimports:
local-prefixes: github.com/retailcrm/api-client-go/v2
lll:
line-length: 160
misspell:
locale: US
nestif:
min-complexity: 4
whitespace:
multi-if: false
multi-func: false
varnamelen:
max-distance: 10
ignore-map-index-ok: true
ignore-type-assert-ok: true
ignore-chan-recv-ok: true
ignore-decls:
- t *testing.T
- e error
- i int
severity:
default-severity: error
case-sensitive: false
service:
golangci-lint-version: 1.62.x

15
.travis.yml Normal file
View file

@ -0,0 +1,15 @@
language: go
go:
- '1.8'
- '1.9'
- '1.10'
- '1.11'
- '1.12'
- '1.13'
before_install:
- go get -v github.com/google/go-querystring/query
- go get -v github.com/h2non/gock
- cp .env.dist .env
script: ./go.test.sh
after_success:
- bash <(curl -s https://codecov.io/bash)

View file

@ -1,6 +1,6 @@
The MIT License (MIT) The MIT License (MIT)
Copyright (c) 2015-2020 RetailDriver LLC Copyright (c) 2015-2018 RetailDriver LLC
Permission is hereby granted, free of charge, to any person obtaining a copy Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal of this software and associated documentation files (the "Software"), to deal

125
README.md
View file

@ -1,60 +1,59 @@
[![Build Status](https://github.com/retailcrm/api-client-go/workflows/ci/badge.svg)](https://github.com/retailcrm/api-client-go/actions) [![Build Status](https://img.shields.io/travis/retailcrm/api-client-go/master.svg?style=flat-square)](https://travis-ci.org/retailcrm/api-client-go)
[![Covarage](https://img.shields.io/codecov/c/gh/retailcrm/api-client-go/master.svg?logo=codecov&logoColor=white)](https://codecov.io/gh/retailcrm/api-client-go) [![Covarage](https://img.shields.io/codecov/c/gh/retailcrm/api-client-go/master.svg?style=flat-square)](https://codecov.io/gh/retailcrm/api-client-go)
[![GitHub release](https://img.shields.io/github/release/retailcrm/api-client-go.svg?logo=github&logoColor=white)](https://github.com/retailcrm/api-client-go/releases) [![GitHub release](https://img.shields.io/github/release/retailcrm/api-client-go.svg?style=flat-square)](https://github.com/retailcrm/api-client-go/releases)
[![Go Report Card](https://goreportcard.com/badge/github.com/retailcrm/api-client-go)](https://goreportcard.com/report/github.com/retailcrm/api-client-go) [![GoLang version](https://img.shields.io/badge/go->=1.8-blue?style=flat-square)](https://golang.org/dl/)
[![GoLang version](https://img.shields.io/badge/go->=1.8-blue)](https://golang.org/dl/) [![Godoc reference](https://img.shields.io/badge/godoc-reference-blue.svg?style=flat-square)](https://godoc.org/github.com/retailcrm/api-client-go)
[![pkg.go.dev](https://img.shields.io/badge/go.dev-reference-007d9c?logo=go&logoColor=white)](https://pkg.go.dev/github.com/retailcrm/api-client-go)
# RetailCRM API Go client # retailCRM API Go client
This is golang RetailCRM API client. This is golang retailCRM API client.
## Installation ## Install
```bash ```bash
go get -u github.com/retailcrm/api-client-go/v2 go get -x github.com/retailcrm/api-client-go
``` ```
## Usage ## Usage
Example: ```golang
```go
package main package main
import ( import (
"log" "fmt"
"net/http"
"github.com/retailcrm/api-client-go/v2" "github.com/retailcrm/api-client-go/v5"
) )
func main() { func main() {
var client = retailcrm.New("https://demo.retailcrm.pro", "09jIJ09j0JKhgyfvyuUIKhiugF") var client = v5.New("https://demo.retailcrm.pro", "09jIJ09j0JKhgyfvyuUIKhiugF")
data, status, err := client.Orders(retailcrm.OrdersRequest{ data, status, err := client.Orders(v5.OrdersRequest{
Filter: retailcrm.OrdersFilter{}, Filter: v5.OrdersFilter{},
Limit: 20, Limit: 20,
Page: 1, Page: 1,
}) },)
if err != nil { if err != nil {
if apiErr, ok := retailcrm.AsAPIError(err); ok { fmt.Printf("%v", err.Error())
log.Fatalf("http status: %d, %s", status, apiErr.String()) }
}
log.Fatalf("http status: %d, error: %s", status, err) if status >= http.StatusBadRequest {
fmt.Printf("%v", err.ApiError())
} }
for _, value := range data.Orders { for _, value := range data.Orders {
log.Printf("%v\n", value.Email) fmt.Printf("%v\n", value.Email)
} }
log.Println(data.Orders[1].FirstName) fmt.Println(data.Orders[1].FirstName)
inventories, status, err := client.InventoriesUpload([]retailcrm.InventoryUpload{ idata, status, err := c.InventoriesUpload(
[]InventoryUpload{
{ {
XMLID: "pTKIKAeghYzX21HTdzFCe1", XMLID: "pTKIKAeghYzX21HTdzFCe1",
Stores: []retailcrm.InventoryUploadStore{ Stores: []InventoryUploadStore{
{ {
Code: "test-store-v5", Code: "test-store-v5",
Available: 10, Available: 10,
@ -74,7 +73,7 @@ func main() {
}, },
{ {
XMLID: "JQIvcrCtiSpOV3AAfMiQB3", XMLID: "JQIvcrCtiSpOV3AAfMiQB3",
Stores: []retailcrm.InventoryUploadStore{ Stores: []InventoryUploadStore{
{ {
Code: "test-store-v5", Code: "test-store-v5",
Available: 45, Available: 45,
@ -95,70 +94,18 @@ func main() {
}, },
) )
if err != nil { if err != nil {
if apiErr, ok := retailcrm.AsAPIError(err); ok { fmt.Printf("%v", err.Error())
log.Fatalf("http status: %d, %s", status, apiErr.String())
}
log.Fatalf("http status: %d, error: %s", status, err)
} }
log.Println(inventories.ProcessedOffersCount) if status >= http.StatusBadRequest {
fmt.Printf("%v", err.ApiError())
}
fmt.Println(idata.processedOffersCount)
} }
``` ```
You can use different error types and `retailcrm.AsAPIError` to process client errors. Example: ## Documentation
```go * [English](http://www.retailcrm.pro/docs/Developers/Index)
package retailcrm * [Russian](http://www.retailcrm.ru/docs/Developers/Index)
import (
"errors"
"log"
"os"
"strings"
"github.com/retailcrm/api-client-go/v2"
)
func main() {
var client = retailcrm.New("https://demo.retailcrm.pro", "09jIJ09j0JKhgyfvyuUIKhiugF")
resp, status, err := client.APICredentials()
if err != nil {
apiErr, ok := retailcrm.AsAPIError(err)
if !ok {
log.Fatalf("http status: %d, error: %s", status, err)
}
switch {
case errors.Is(apiErr, retailcrm.ErrMissingCredentials):
log.Fatalln("No API key provided.")
case errors.Is(apiErr, retailcrm.ErrInvalidCredentials):
log.Fatalln("Invalid API key.")
case errors.Is(apiErr, retailcrm.ErrAccessDenied):
log.Fatalln("Access denied. Please check that the provided key has access to the credentials info.")
case errors.Is(apiErr, retailcrm.ErrAccountDoesNotExist):
log.Fatalln("There is no RetailCRM at the provided URL.")
case errors.Is(apiErr, retailcrm.ErrMissingParameter):
// retailcrm.APIError in this case will always contain "Name" key in the errors list with the parameter name.
log.Fatalln("This parameter should be present:", apiErr.Errors()["Name"])
case errors.Is(apiErr, retailcrm.ErrValidation):
log.Println("Validation errors from the API:")
for name, value := range apiErr.Errors() {
log.Printf(" - %s: %s\n", name, value)
}
os.Exit(1)
case errors.Is(apiErr, retailcrm.ErrGeneric):
log.Fatalf("failure from the API. %s", apiErr.String())
}
}
log.Println("Available scopes:", strings.Join(resp.Scopes, ", "))
}
```
## Upgrading
Please check the [UPGRADING.md](UPGRADING.md) to learn how to upgrade to the new version.

View file

@ -1,70 +0,0 @@
# Upgrading to the v2
### Install the new version
```bash
go get -u github.com/retailcrm/api-client-go/v2
```
### Update all imports
Before:
```go
package main
import v5 "github.com/retailcrm/api-client-go/v5"
```
After:
```go
package main
import "github.com/retailcrm/api-client-go/v2"
```
You can use package alias `v5` to skip the second step.
### Replace package name for all imported symbols
Before:
```go
package main
import v5 "github.com/retailcrm/api-client-go/v5"
func main() {
client := v5.New("https://test.retailcrm.pro", "key")
data, status, err := client.Orders(v5.OrdersRequest{
Filter: v5.OrdersFilter{
City: "Moscow",
},
Page: 1,
})
...
}
```
After:
```go
package main
import "github.com/retailcrm/api-client-go/v2"
func main() {
client := retailcrm.New("https://test.retailcrm.pro", "key")
data, status, err := client.Orders(retailcrm.OrdersRequest{
Filter: retailcrm.OrdersFilter{
City: "Moscow",
},
Page: 1,
})
...
}
```
### Upgrade client usages
This major release contains some breaking changes regarding field names and fully redesigned error handling. Use the second example from
the readme to learn how to process errors correctly.

7224
client.go

File diff suppressed because it is too large Load diff

View file

@ -1,8 +0,0 @@
package retailcrm
var UserGroupSuperadmins UserGroupType = "superadmins"
var (
NotificationTypeError NotificationType = "api.error"
NotificationTypeInfo NotificationType = "api.info"
)

194
error.go
View file

@ -1,194 +0,0 @@
package retailcrm
import (
"encoding/json"
"fmt"
"regexp"
"strings"
)
var missingParameterMatcher = regexp.MustCompile(`^Parameter \'([\w\]\[\_\-]+)\' is missing$`)
var (
// ErrRateLimited will be returned if request was rate limited.
ErrRateLimited = NewAPIError("rate limit exceeded")
// ErrMissingCredentials will be returned if no API key was provided to the API.
ErrMissingCredentials = NewAPIError(`apiKey is missing`)
// ErrInvalidCredentials will be returned if provided API key is invalid.
ErrInvalidCredentials = NewAPIError(`wrong "apiKey" value`)
// ErrAccessDenied will be returned in case of "Access denied" error.
ErrAccessDenied = NewAPIError("access denied")
// ErrAccountDoesNotExist will be returned if target system does not exist.
ErrAccountDoesNotExist = NewAPIError("account does not exist")
// ErrValidation will be returned in case of validation errors.
ErrValidation = NewAPIError("validation error")
// ErrMissingParameter will be returned if parameter is missing.
// Underlying error messages list will contain parameter name in the "Name" key.
ErrMissingParameter = NewAPIError("missing parameter")
// ErrGeneric will be returned if error cannot be classified as one of the errors above.
ErrGeneric = NewAPIError("API error")
)
// APIErrorsList struct.
type APIErrorsList map[string]string
// APIError returns when an API error was occurred.
type APIError interface {
error
fmt.Stringer
withWrapped(error) APIError
withErrors(APIErrorsList) APIError
Unwrap() error
Errors() APIErrorsList
}
type apiError struct {
ErrorMsg string `json:"errorMsg,omitempty"`
ErrorsList APIErrorsList `json:"errors,omitempty"`
wrapped error
}
// CreateAPIError from the provided response data. Different error types will be returned depending on the response,
// all of them can be matched using errors.Is. APi errors will always implement APIError interface.
func CreateAPIError(dataResponse []byte) error {
a := &apiError{}
if len(dataResponse) > 0 && dataResponse[0] == '<' {
return ErrAccountDoesNotExist
}
if err := json.Unmarshal(dataResponse, &a); err != nil {
return err
}
var found APIError
switch a.ErrorMsg {
case `"apiKey" is missing.`:
found = ErrMissingCredentials
case `Wrong "apiKey" value.`:
found = ErrInvalidCredentials
case "Access denied.":
found = ErrAccessDenied
case "Account does not exist.":
found = ErrAccountDoesNotExist
case "Errors in the entity format":
fallthrough
case "Validation error":
found = ErrValidation
default:
if param, ok := asMissingParameterErr(a.ErrorMsg); ok {
return a.withWrapped(ErrMissingParameter).withErrors(APIErrorsList{"Name": param})
}
found = ErrGeneric
}
result := NewAPIError(a.ErrorMsg).withWrapped(found)
if len(a.ErrorsList) > 0 {
return result.withErrors(a.ErrorsList)
}
return result
}
// CreateGenericAPIError for the situations when API response cannot be processed, but response was actually received.
func CreateGenericAPIError(message string) APIError {
return NewAPIError(message).withWrapped(ErrGeneric)
}
// NewAPIError returns API error with the provided message.
func NewAPIError(message string) APIError {
return &apiError{ErrorMsg: message}
}
// AsAPIError returns APIError and true if provided error is an APIError or contains wrapped APIError.
// Returns (nil, false) otherwise.
func AsAPIError(err error) (APIError, bool) {
apiErr := unwrapAPIError(err)
return apiErr, apiErr != nil
}
func unwrapAPIError(err error) APIError {
if err == nil {
return nil
}
if apiErr, ok := err.(APIError); ok { // nolint:errorlint
return apiErr
}
wrapper, ok := err.(interface { // nolint:errorlint
Unwrap() error
})
if ok {
return unwrapAPIError(wrapper.Unwrap())
}
return nil
}
// asMissingParameterErr returns true if "Parameter 'name' is missing" error message is provided.
func asMissingParameterErr(message string) (string, bool) {
matches := missingParameterMatcher.FindAllStringSubmatch(message, -1)
if len(matches) == 1 && len(matches[0]) == 2 {
return matches[0][1], true
}
return "", false
}
// Error returns errorMsg field from the response.
func (e *apiError) Error() string {
return e.ErrorMsg
}
// Unwrap returns wrapped error. It is usually one of the predefined types like ErrGeneric or ErrValidation.
// It can be used directly, but it's main purpose is to make errors matchable via errors.Is call.
func (e *apiError) Unwrap() error {
return e.wrapped
}
// Errors returns errors field from the response.
func (e *apiError) Errors() APIErrorsList {
return e.ErrorsList
}
// String returns string representation of an APIError.
func (e *apiError) String() string {
var sb strings.Builder
sb.Grow(256) // nolint:gomnd
sb.WriteString(fmt.Sprintf(`errorMsg: "%s"`, e.Error()))
if len(e.Errors()) > 0 {
i := 0
useIndex := true
errorList := make([]string, len(e.Errors()))
for index, errText := range e.Errors() {
if i == 0 && index == "0" {
useIndex = false
}
if useIndex {
errorList[i] = fmt.Sprintf(`%s: "%s"`, index, errText)
} else {
errorList[i] = errText
}
i++
}
sb.WriteString(", errors: [" + strings.Join(errorList, ", ") + "]")
}
return sb.String()
}
// withWrapped is a wrapped setter.
func (e *apiError) withWrapped(err error) APIError {
e.wrapped = err
return e
}
// withErrors is an ErrorsList setter.
func (e *apiError) withErrors(m APIErrorsList) APIError {
e.ErrorsList = m
return e
}

View file

@ -1,171 +0,0 @@
package retailcrm
import (
"testing"
"github.com/stretchr/testify/suite"
)
type ErrorTest struct {
suite.Suite
}
func TestError(t *testing.T) {
suite.Run(t, new(ErrorTest))
}
func (t *ErrorTest) TestFailure_ApiErrorsSlice() {
b := []byte(`{"success": false,
"errorMsg": "Failed to activate module",
"errors": [
"Your account has insufficient funds to activate integration module",
"Test error"
]}`)
expected := APIErrorsList{
"0": "Your account has insufficient funds to activate integration module",
"1": "Test error",
}
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().ErrorIs(e, ErrGeneric)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Assert().Equal(expected, apiErr.Errors())
}
func (t *ErrorTest) TestFailure_ApiErrorsMap() {
b := []byte(`{"success": false,
"errorMsg": "Failed to activate module",
"errors": {"id": "ID must be an integer", "test": "Test error"}}`,
)
expected := APIErrorsList{
"id": "ID must be an integer",
"test": "Test error",
}
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().ErrorIs(e, ErrGeneric)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Assert().Equal(expected, apiErr.Errors())
}
func (t *ErrorTest) TestFailure_APIKeyMissing() {
b := []byte(`{"success": false,
"errorMsg": "\"apiKey\" is missing."}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrMissingCredentials)
}
func (t *ErrorTest) TestFailure_APIKeyWrong() {
b := []byte(`{"success": false,
"errorMsg": "Wrong \"apiKey\" value."}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrInvalidCredentials)
}
func (t *ErrorTest) TestFailure_AccessDenied() {
b := []byte(`{"success": false,
"errorMsg": "Access denied."}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrAccessDenied)
}
func (t *ErrorTest) TestFailure_AccountDoesNotExist() {
b := []byte(`{"success": false,
"errorMsg": "Account does not exist."}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrAccountDoesNotExist)
}
func (t *ErrorTest) TestFailure_Validation() {
b := []byte(`{"success": false,
"errorMsg": "Errors in the entity format",
"errors": {"name": "name must be provided"}}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrValidation)
t.Assert().Equal("name must be provided", apiErr.Errors()["name"])
}
func (t *ErrorTest) TestFailure_Validation2() {
b := []byte(`{"success": false,
"errorMsg": "Validation error",
"errors": {"name": "name must be provided"}}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrValidation)
t.Assert().Equal("name must be provided", apiErr.Errors()["name"])
t.Assert().Equal("errorMsg: \"Validation error\", errors: [name: \"name must be provided\"]", apiErr.String())
}
func (t *ErrorTest) TestFailure_MissingParameter() {
b := []byte(`{"success": false,
"errorMsg": "Parameter 'item' is missing"}`,
)
e := CreateAPIError(b)
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Require().ErrorIs(e, ErrMissingParameter)
t.Assert().Equal("item", apiErr.Errors()["Name"])
}
func (t *ErrorTest) Test_CreateGenericAPIError() {
e := CreateGenericAPIError("generic error message")
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Assert().ErrorIs(apiErr, ErrGeneric)
t.Assert().Equal("generic error message", e.Error())
}
func (t *ErrorTest) TestFailure_HTML() {
e := CreateAPIError([]byte{'<'})
apiErr, ok := AsAPIError(e)
t.Require().NotNil(apiErr)
t.Require().True(ok)
t.Assert().ErrorIs(apiErr, ErrAccountDoesNotExist)
}

75
errs/error.go Normal file
View file

@ -0,0 +1,75 @@
package errs
import (
"encoding/json"
"fmt"
"strconv"
)
// Error returns the string representation of the error and satisfies the error interface.
func (f *Failure) Error() string {
if f != nil && f.runtimeErr != nil {
return f.runtimeErr.Error()
}
return ""
}
// ApiError returns formatted string representation of the API error
func (f *Failure) ApiError() string {
if f != nil && f.apiErr != "" {
return fmt.Sprintf("%+v", f.apiErr)
}
return ""
}
// ApiErrors returns array of formatted strings that represents API errors
func (f *Failure) ApiErrors() map[string]string {
if len(f.apiErrs) > 0 {
return f.apiErrs
}
return nil
}
// SetRuntimeError set runtime error value
func (f *Failure) SetRuntimeError(e error) {
f.runtimeErr = e
}
// SetApiError set api error value
func (f *Failure) SetApiError(e string) {
f.apiErr = e
}
// SetApiErrors set api errors value
func (f *Failure) SetApiErrors(e map[string]string) {
f.apiErrs = e
}
// ErrorsHandler returns map
func ErrorsHandler(errs interface{}) map[string]string {
m := make(map[string]string)
switch errs.(type) {
case map[string]interface{}:
for idx, val := range errs.(map[string]interface{}) {
m[idx] = val.(string)
}
case []interface{}:
for idx, val := range errs.([]interface{}) {
m[strconv.Itoa(idx)] = val.(string)
}
}
return m
}
// ErrorResponse method
func ErrorResponse(data []byte) (FailureResponse, error) {
var resp FailureResponse
err := json.Unmarshal(data, &resp)
return resp, err
}

50
errs/error_test.go Normal file
View file

@ -0,0 +1,50 @@
package errs
import (
"reflect"
"testing"
)
func TestFailure_ApiErrorsSlice(t *testing.T) {
var err = Failure{}
b := []byte(`{"success": false, "errorMsg": "Failed to activate module", "errors": ["Your account has insufficient funds to activate integration module"]}`)
expected := map[string]string{
"0": "Your account has insufficient funds to activate integration module",
}
resp, e := ErrorResponse(b)
err.SetRuntimeError(e)
err.SetApiError(resp.ErrorMsg)
if resp.Errors != nil {
err.SetApiErrors(ErrorsHandler(resp.Errors))
}
eq := reflect.DeepEqual(expected, err.ApiErrors())
if eq != true {
t.Errorf("%+v", eq)
}
}
func TestFailure_ApiErrorsMap(t *testing.T) {
var err = Failure{}
b := []byte(`{"success": false, "errorMsg": "Failed to activate module", "errors": {"id": "ID must be an integer"}}`)
expected := map[string]string{
"id": "ID must be an integer",
}
resp, e := ErrorResponse(b)
err.SetRuntimeError(e)
err.SetApiError(resp.ErrorMsg)
if resp.Errors != nil {
err.SetApiErrors(ErrorsHandler(resp.Errors))
}
eq := reflect.DeepEqual(expected, err.ApiErrors())
if eq != true {
t.Errorf("%+v", eq)
}
}

8
errs/interfaces.go Normal file
View file

@ -0,0 +1,8 @@
package errs
// Error implements generic error interface
type Error interface {
error
ApiError() string
ApiErrors() map[string]string
}

14
errs/types.go Normal file
View file

@ -0,0 +1,14 @@
package errs
// Failure struct implode runtime & api errors
type Failure struct {
runtimeErr error
apiErr string
apiErrs map[string]string
}
// FailureResponse convert json error response into object
type FailureResponse struct {
ErrorMsg string `json:"errorMsg,omitempty"`
Errors interface{} `json:"errors,omitempty"`
}

10
go.mod
View file

@ -1,10 +0,0 @@
module github.com/retailcrm/api-client-go/v2
go 1.13
require (
github.com/google/go-querystring v1.1.0
github.com/joho/godotenv v1.3.0
github.com/stretchr/testify v1.7.0
gopkg.in/h2non/gock.v1 v1.1.2
)

25
go.sum
View file

@ -1,25 +0,0 @@
github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8=
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
github.com/google/go-cmp v0.5.2 h1:X2ev0eStA3AbceY54o37/0PQ/UWqKEiiO2dKL5OPaFM=
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542 h1:2VTzZjLZBgl62/EtslCrtky5vbi9dd7HrQPQIx6wqiw=
github.com/h2non/parth v0.0.0-20190131123155-b4df798d6542/go.mod h1:Ow0tF8D4Kplbc8s8sSb3V2oUCygFHVp8gC3Dn6U4MNI=
github.com/joho/godotenv v1.3.0 h1:Zjp+RcGpHhGlrMbJzXTrZZPrWj+1vfm90La1wgB6Bhc=
github.com/joho/godotenv v1.3.0/go.mod h1:7hK45KPybAkOC6peb+G5yklZfMxEjkZhHbwpqxOKXbg=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32 h1:W6apQkHrMkS0Muv8G/TipAy/FJl/rCYT0+EuS8+Z0z4=
github.com/nbio/st v0.0.0-20140626010706-e9e8d9816f32/go.mod h1:9wM+0iRr9ahx58uYLpLIr5fm8diHn0JbqRycJi6w0Ms=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IVDexMakfv52eLZ2CXBWiKr4=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/h2non/gock.v1 v1.1.2 h1:jBbHXgGBK/AoPVfJh5x4r/WxIrElvbLel8TCZkkZJoY=
gopkg.in/h2non/gock.v1 v1.1.2/go.mod h1:n7UGz/ckNChHiK05rDoiC4MYSunEC/lyaUm2WWaDva0=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=

15
go.test.sh Executable file
View file

@ -0,0 +1,15 @@
#!/usr/bin/env bash
set -e
export DEVELOPER_NODE=1
export RETAILCRM_URL=https://test.retailcrm.pro
export RETAILCRM_KEY=key
echo "" > coverage.txt
for d in $(go list ./... | grep -v vendor); do
go test -race -coverprofile=profile.out -covermode=atomic "$d"
if [ -f profile.out ]; then
cat profile.out >> coverage.txt
rm profile.out
fi
done

25
log.go
View file

@ -1,25 +0,0 @@
package retailcrm
// BasicLogger provides basic functionality for logging.
type BasicLogger interface {
Printf(string, ...interface{})
}
// DebugLogger can be used to easily wrap any logger with Debugf method into the BasicLogger instance.
type DebugLogger interface {
Debugf(string, ...interface{})
}
type debugLoggerAdapter struct {
logger DebugLogger
}
// DebugLoggerAdapter returns BasicLogger that calls underlying DebugLogger.Debugf.
func DebugLoggerAdapter(logger DebugLogger) BasicLogger {
return &debugLoggerAdapter{logger: logger}
}
// Printf data in the log using DebugLogger.Debugf.
func (l *debugLoggerAdapter) Printf(format string, v ...interface{}) {
l.logger.Debugf(format, v...)
}

View file

@ -1,24 +0,0 @@
package retailcrm
import (
"fmt"
"testing"
"github.com/stretchr/testify/assert"
)
type wrappedLogger struct {
lastMessage string
}
func (w *wrappedLogger) Debugf(msg string, v ...interface{}) {
w.lastMessage = fmt.Sprintf(msg, v...)
}
func TestDebugLoggerAdapter_Printf(t *testing.T) {
wrapped := &wrappedLogger{}
logger := DebugLoggerAdapter(wrapped)
logger.Printf("Test message #%d", 1)
assert.Equal(t, "Test message #1", wrapped.lastMessage)
}

View file

@ -1,160 +0,0 @@
package retailcrm
import (
"encoding/json"
"fmt"
"strconv"
)
func (t Tag) MarshalJSON() ([]byte, error) {
return json.Marshal(t.Name)
}
func (a *APIErrorsList) UnmarshalJSON(data []byte) error {
var i interface{}
var m APIErrorsList
if err := json.Unmarshal(data, &i); err != nil {
return err
}
switch e := i.(type) {
case map[string]interface{}:
m = make(APIErrorsList, len(e))
for idx, val := range e {
m[idx] = fmt.Sprint(val)
}
case []interface{}:
m = make(APIErrorsList, len(e))
for idx, val := range e {
m[strconv.Itoa(idx)] = fmt.Sprint(val)
}
}
*a = m
return nil
}
func (l *StringMap) UnmarshalJSON(data []byte) error {
var i interface{}
var m StringMap
if err := json.Unmarshal(data, &i); err != nil {
return err
}
switch e := i.(type) {
case map[string]interface{}:
m = make(StringMap, len(e))
for idx, val := range e {
m[idx] = fmt.Sprint(val)
}
case []interface{}:
m = make(StringMap, len(e))
for idx, val := range e {
m[strconv.Itoa(idx)] = fmt.Sprint(val)
}
}
*l = m
return nil
}
func (l *CustomFieldMap) UnmarshalJSON(data []byte) error {
var i interface{}
var items CustomFieldMap
if err := json.Unmarshal(data, &i); err != nil {
return err
}
switch e := i.(type) {
case map[string]interface{}:
items = make(CustomFieldMap, len(e))
for idx, val := range e {
items[idx] = val
}
case []interface{}:
items = make(CustomFieldMap, len(e))
for idx, val := range e {
items[strconv.Itoa(idx)] = val
}
}
*l = items
return nil
}
func (p *OrderPayments) UnmarshalJSON(data []byte) error {
var i interface{}
var m OrderPayments
if err := json.Unmarshal(data, &i); err != nil {
return err
}
switch e := i.(type) {
case map[string]interface{}:
m = make(OrderPayments, len(e))
for idx, val := range e {
var res OrderPayment
err := unmarshalMap(val.(map[string]interface{}), &res)
if err != nil {
return err
}
m[idx] = res
}
case []interface{}:
m = make(OrderPayments, len(e))
for idx, val := range e {
var res OrderPayment
err := unmarshalMap(val.(map[string]interface{}), &res)
if err != nil {
return err
}
m[strconv.Itoa(idx)] = res
}
}
*p = m
return nil
}
func (p *Properties) UnmarshalJSON(data []byte) error {
var i interface{}
var m Properties
if err := json.Unmarshal(data, &i); err != nil {
return err
}
switch e := i.(type) {
case map[string]interface{}:
m = make(Properties, len(e))
for idx, val := range e {
var res Property
err := unmarshalMap(val.(map[string]interface{}), &res)
if err != nil {
return err
}
m[idx] = res
}
case []interface{}:
m = make(Properties, len(e))
for idx, val := range e {
var res Property
err := unmarshalMap(val.(map[string]interface{}), &res)
if err != nil {
return err
}
m[strconv.Itoa(idx)] = res
}
}
*p = m
return nil
}
func unmarshalMap(m map[string]interface{}, v interface{}) (err error) {
var data []byte
data, err = json.Marshal(m)
if err != nil {
return err
}
return json.Unmarshal(data, v)
}

View file

@ -1,102 +0,0 @@
package retailcrm
import (
"encoding/json"
"reflect"
"testing"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
)
func TestTag_MarshalJSON(t *testing.T) {
tags := []Tag{
{"first", "#3e89b6", false},
{"second", "#ffa654", false},
}
names := []byte(`["first","second"]`)
str, err := json.Marshal(tags)
if err != nil {
t.Errorf("%v", err.Error())
}
if !reflect.DeepEqual(str, names) {
t.Errorf("Marshaled: %#v\nExpected: %#v\n", str, names)
}
}
func TestAPIErrorsList_UnmarshalJSON(t *testing.T) {
var list APIErrorsList
require.NoError(t, json.Unmarshal([]byte(`["first", "second"]`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["0"], "first")
assert.Equal(t, list["1"], "second")
require.NoError(t, json.Unmarshal([]byte(`{"a": "first", "b": "second"}`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["a"], "first")
assert.Equal(t, list["b"], "second")
require.NoError(t, json.Unmarshal([]byte(`[]`), &list))
assert.Len(t, list, 0)
}
func TestCustomFieldsList_UnmarshalJSON(t *testing.T) {
var list CustomFieldMap
require.NoError(t, json.Unmarshal([]byte(`["first", "second"]`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["0"], "first")
assert.Equal(t, list["1"], "second")
require.NoError(t, json.Unmarshal([]byte(`{"a": "first", "b": "second"}`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["a"], "first")
assert.Equal(t, list["b"], "second")
require.NoError(t, json.Unmarshal([]byte(`{"a": ["first", "second"], "b": "second"}`), &list))
assert.Len(t, list, 2)
assert.Len(t, list["a"].([]interface{}), 2)
assert.Equal(t, list["a"].([]interface{})[0], "first")
assert.Equal(t, list["a"].([]interface{})[1], "second")
assert.Equal(t, list["b"], "second")
require.NoError(t, json.Unmarshal([]byte(`[]`), &list))
assert.Len(t, list, 0)
}
func TestOrderPayments_UnmarshalJSON(t *testing.T) {
var list OrderPayments
require.NoError(t, json.Unmarshal([]byte(`[{"id": 1}, {"id": 2}]`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["0"], OrderPayment{ID: 1})
assert.Equal(t, list["1"], OrderPayment{ID: 2})
require.NoError(t, json.Unmarshal([]byte(`{"a": {"id": 1}, "b": {"id": 2}}`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["a"], OrderPayment{ID: 1})
assert.Equal(t, list["b"], OrderPayment{ID: 2})
require.NoError(t, json.Unmarshal([]byte(`[]`), &list))
assert.Len(t, list, 0)
}
func TestProperties_UnmarshalJSON(t *testing.T) {
var list Properties
require.NoError(t, json.Unmarshal([]byte(`[{"code": "first"}, {"code": "second"}]`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["0"], Property{Code: "first"})
assert.Equal(t, list["1"], Property{Code: "second"})
require.NoError(t, json.Unmarshal([]byte(`{"a": {"code": "first"}, "b": {"code": "second"}}`), &list))
assert.Len(t, list, 2)
assert.Equal(t, list["a"], Property{Code: "first"})
assert.Equal(t, list["b"], Property{Code: "second"})
require.NoError(t, json.Unmarshal([]byte(`[]`), &list))
assert.Len(t, list, 0)
}

View file

@ -1,43 +0,0 @@
package retailcrm
import (
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
"testing"
"github.com/stretchr/testify/suite"
)
type ConnectRequestTest struct {
suite.Suite
}
func TestConnectRequest(t *testing.T) {
suite.Run(t, new(ConnectRequestTest))
}
func (t *ConnectRequestTest) Test_SystemURL() {
t.Assert().Equal("", ConnectRequest{}.SystemURL())
t.Assert().Equal("https://test.retailcrm.pro", ConnectRequest{URL: "https://test.retailcrm.pro"}.SystemURL())
t.Assert().Equal("https://test.retailcrm.pro", ConnectRequest{URL: "https://test.retailcrm.pro/"}.SystemURL())
}
func (t *ConnectRequestTest) Test_Verify() {
t.Assert().True(ConnectRequest{
APIKey: "key",
Token: createConnectToken("key", "secret"),
}.Verify("secret"))
t.Assert().False(ConnectRequest{
APIKey: "key",
Token: createConnectToken("key", "secret2"),
}.Verify("secret"))
}
func createConnectToken(apiKey, secret string) string {
mac := hmac.New(sha256.New, []byte(secret))
if _, err := mac.Write([]byte(apiKey)); err != nil {
panic(err)
}
return hex.EncodeToString(mac.Sum(nil))
}

View file

@ -1,699 +0,0 @@
package retailcrm
// SuccessfulResponse type.
type SuccessfulResponse struct {
Success bool `json:"success"`
}
type CreateLoyaltyAccountResponse struct {
SuccessfulResponse
LoyaltyAccount LoyaltyAccount `json:"loyaltyAccount,omitempty"`
Warnings []string `json:"warnings,omitempty"`
}
type EditLoyaltyAccountResponse struct {
SuccessfulResponse
LoyaltyAccount LoyaltyAccount `json:"loyaltyAccount,omitempty"`
}
// CreateResponse type.
type CreateResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
}
// OrderCreateResponse type.
type OrderCreateResponse struct {
CreateResponse
Order Order `json:"order,omitempty"`
}
// OperationResponse type.
type OperationResponse struct {
Success bool `json:"success"`
Errors map[string]string `json:"ErrorsList,omitempty"`
}
// VersionResponse return available API versions.
type VersionResponse struct {
Success bool `json:"success,omitempty"`
Versions []string `json:"versions,omitempty"`
}
// CredentialResponse return available API methods.
type CredentialResponse struct {
Success bool `json:"success,omitempty"`
// deprecated
Credentials []string `json:"credentials,omitempty"`
Scopes []string `json:"scopes,omitempty"`
SiteAccess string `json:"siteAccess,omitempty"`
SitesAvailable []string `json:"sitesAvailable,omitempty"`
}
// SystemInfoResponse return system info.
type SystemInfoResponse struct {
Success bool `json:"success,omitempty"`
SystemVersion string `json:"systemVersion,omitempty"`
PublicURL string `json:"publicUrl,omitempty"`
TechnicalURL string `json:"technicalUrl,omitempty"`
}
// CustomerResponse type.
type CustomerResponse struct {
Success bool `json:"success"`
Customer *Customer `json:"customer,omitempty"`
}
// CorporateCustomerResponse type.
type CorporateCustomerResponse struct {
Success bool `json:"success"`
CorporateCustomer *CorporateCustomer `json:"customerCorporate,omitempty"`
}
// CustomersResponse type.
type CustomersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Customers []Customer `json:"customers,omitempty"`
}
// CorporateCustomersResponse type.
type CorporateCustomersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomersCorporate []CorporateCustomer `json:"customersCorporate,omitempty"`
}
// CorporateCustomersNotesResponse type.
type CorporateCustomersNotesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Notes []Note `json:"notes,omitempty"`
}
// CorporateCustomersAddressesResponse type.
type CorporateCustomersAddressesResponse struct {
Success bool `json:"success"`
Addresses []CorporateCustomerAddress `json:"addresses"`
}
// CorporateCustomerCompaniesResponse type.
type CorporateCustomerCompaniesResponse struct {
Success bool `json:"success"`
Companies []Company `json:"companies"`
}
// CorporateCustomerContactsResponse type.
type CorporateCustomerContactsResponse struct {
Success bool `json:"success"`
Contacts []CorporateCustomerContact `json:"contacts"`
}
// CustomerChangeResponse type.
type CustomerChangeResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
State string `json:"state,omitempty"`
}
// CorporateCustomerChangeResponse type.
type CorporateCustomerChangeResponse CustomerChangeResponse
// CustomersUploadResponse type.
type CustomersUploadResponse struct {
Success bool `json:"success"`
UploadedCustomers []IdentifiersPair `json:"uploadedCustomers,omitempty"`
FailedCustomers []ExternalID `json:"failedCustomers,omitempty"`
}
// CorporateCustomersUploadResponse type.
type CorporateCustomersUploadResponse CustomersUploadResponse
// CustomersHistoryResponse type.
type CustomersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []CustomerHistoryRecord `json:"history,omitempty"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// CorporateCustomersHistoryResponse type.
type CorporateCustomersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []CorporateCustomerHistoryRecord `json:"history,omitempty"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// OrderResponse type.
type OrderResponse struct {
Success bool `json:"success"`
Order *Order `json:"order,omitempty"`
}
// OrdersResponse type.
type OrdersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Orders []Order `json:"orders,omitempty"`
}
// OrdersStatusesResponse type.
type OrdersStatusesResponse struct {
Success bool `json:"success"`
Orders []OrdersStatus `json:"orders"`
}
// OrdersUploadResponse type.
type OrdersUploadResponse struct {
Success bool `json:"success"`
UploadedOrders []IdentifiersPair `json:"uploadedOrders,omitempty"`
FailedOrders []ExternalID `json:"failedOrders,omitempty"`
}
// OrdersHistoryResponse type.
type OrdersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []OrdersHistoryRecord `json:"history,omitempty"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// PackResponse type.
type PackResponse struct {
Success bool `json:"success"`
Pack *Pack `json:"pack,omitempty"`
}
// PacksResponse type.
type PacksResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Packs []Pack `json:"packs,omitempty"`
}
// PacksHistoryResponse type.
type PacksHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []PacksHistoryRecord `json:"history,omitempty"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// UserResponse type.
type UserResponse struct {
Success bool `json:"success"`
User *User `json:"user,omitempty"`
}
// UsersResponse type.
type UsersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Users []User `json:"users,omitempty"`
}
// UserGroupsResponse type.
type UserGroupsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Groups []UserGroup `json:"groups,omitempty"`
}
// TaskResponse type.
type TaskResponse struct {
Success bool `json:"success"`
Task *Task `json:"task,omitempty"`
}
// TasksResponse type.
type TasksResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Tasks []Task `json:"tasks,omitempty"`
}
// NotesResponse type.
type NotesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Notes []Note `json:"notes,omitempty"`
}
// SegmentsResponse type.
type SegmentsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Segments []Segment `json:"segments,omitempty"`
}
// SettingsResponse type.
type SettingsResponse struct {
Success bool `json:"success"`
Settings Settings `json:"settings,omitempty"`
}
// CountriesResponse type.
type CountriesResponse struct {
Success bool `json:"success"`
CountriesIso []string `json:"countriesIso,omitempty"`
}
// CostGroupsResponse type.
type CostGroupsResponse struct {
Success bool `json:"success"`
CostGroups []CostGroup `json:"costGroups,omitempty"`
}
// CostItemsResponse type.
type CostItemsResponse struct {
Success bool `json:"success"`
CostItems []CostItem `json:"costItems,omitempty"`
}
// CouriersResponse type.
type CouriersResponse struct {
Success bool `json:"success"`
Couriers []Courier `json:"couriers,omitempty"`
}
// DeliveryServiceResponse type.
type DeliveryServiceResponse struct {
Success bool `json:"success"`
DeliveryServices map[string]DeliveryService `json:"deliveryServices,omitempty"`
}
// DeliveryTypesResponse type.
type DeliveryTypesResponse struct {
Success bool `json:"success"`
DeliveryTypes map[string]DeliveryType `json:"deliveryTypes,omitempty"`
}
// LegalEntitiesResponse type.
type LegalEntitiesResponse struct {
Success bool `json:"success"`
LegalEntities []LegalEntity `json:"legalEntities,omitempty"`
}
// OrderMethodsResponse type.
type OrderMethodsResponse struct {
Success bool `json:"success"`
OrderMethods map[string]OrderMethod `json:"orderMethods,omitempty"`
}
// OrderTypesResponse type.
type OrderTypesResponse struct {
Success bool `json:"success"`
OrderTypes map[string]OrderType `json:"orderTypes,omitempty"`
}
// PaymentStatusesResponse type.
type PaymentStatusesResponse struct {
Success bool `json:"success"`
PaymentStatuses map[string]PaymentStatus `json:"paymentStatuses,omitempty"`
}
// PaymentTypesResponse type.
type PaymentTypesResponse struct {
Success bool `json:"success"`
PaymentTypes map[string]PaymentType `json:"paymentTypes,omitempty"`
}
// PriceTypesResponse type.
type PriceTypesResponse struct {
Success bool `json:"success"`
PriceTypes []PriceType `json:"priceTypes,omitempty"`
}
// ProductStatusesResponse type.
type ProductStatusesResponse struct {
Success bool `json:"success"`
ProductStatuses map[string]ProductStatus `json:"productStatuses,omitempty"`
}
// StatusesResponse type.
type StatusesResponse struct {
Success bool `json:"success"`
Statuses map[string]Status `json:"statuses,omitempty"`
}
// StatusGroupsResponse type.
type StatusGroupsResponse struct {
Success bool `json:"success"`
StatusGroups map[string]StatusGroup `json:"statusGroups,omitempty"`
}
// SitesResponse type.
type SitesResponse struct {
Success bool `json:"success"`
Sites map[string]Site `json:"sites,omitempty"`
}
// StoresResponse type.
type StoresResponse struct {
Success bool `json:"success"`
Stores []Store `json:"stores,omitempty"`
}
// InventoriesResponse type.
type InventoriesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Offers []Offer `json:"offers,omitempty"`
}
// StoreUploadResponse type.
type StoreUploadResponse struct {
Success bool `json:"success"`
ProcessedOffersCount int `json:"processedOffersCount,omitempty"`
NotFoundOffers []Offer `json:"notFoundOffers,omitempty"`
}
// ProductsGroupsResponse type.
type ProductsGroupsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
ProductGroup []ProductGroup `json:"productGroup,omitempty"`
}
// ProductsResponse type.
type ProductsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Products []Product `json:"products,omitempty"`
}
type ProductEditNotFoundResponse struct {
ID string `json:"id"`
ExternalID string `json:"externalId,omitempty"`
}
type ProductsBatchEditResponse struct {
SuccessfulResponse
ProcessedProductsCount int `json:"processedProductsCount,omitempty"`
NotFoundProducts []ProductEditNotFoundResponse `json:"notFoundProducts,omitempty"`
}
type ProductsBatchCreateResponse struct {
SuccessfulResponse
ProcessedProductsCount int `json:"processedProductsCount,omitempty"`
AddedProducts []int `json:"addedProducts,omitempty"`
}
// ProductsPropertiesResponse type.
type ProductsPropertiesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Properties []Property `json:"properties,omitempty"`
}
// CartResponse type.
type CartResponse struct {
SuccessfulResponse
Cart Cart `json:"cart"`
}
// DeliveryShipmentsResponse type.
type DeliveryShipmentsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
DeliveryShipments []DeliveryShipment `json:"deliveryShipments,omitempty"`
}
// DeliveryShipmentResponse type.
type DeliveryShipmentResponse struct {
Success bool `json:"success"`
DeliveryShipment *DeliveryShipment `json:"deliveryShipment,omitempty"`
}
// DeliveryShipmentUpdateResponse type.
type DeliveryShipmentUpdateResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
Status string `json:"status,omitempty"`
}
// IntegrationModuleResponse type.
type IntegrationModuleResponse struct {
Success bool `json:"success"`
IntegrationModule *IntegrationModule `json:"integrationModule,omitempty"`
}
// UpdateScopesResponse update scopes response.
type UpdateScopesResponse struct {
ErrorResponse
APIKey string `json:"apiKey"`
}
// IntegrationModuleEditResponse type.
type IntegrationModuleEditResponse struct {
Success bool `json:"success"`
Info ResponseInfo `json:"info,omitempty"`
}
// ResponseInfo type.
type ResponseInfo struct {
MgTransportInfo MgInfo `json:"mgTransport,omitempty"`
MgBotInfo MgInfo `json:"mgBot,omitempty"`
BillingInfo *BillingInfo `json:"billingInfo,omitempty"`
DeliveryTypeInfo DeliveryTypeInfo `json:"deliveryType,omitempty"`
}
type BillingInfo struct {
Price float64 `json:"price,omitempty"`
PriceWithDiscount float64 `json:"priceWithDiscount,omitempty"`
BillingType string `json:"billingType,omitempty"`
Currency *BillingInfoCurrency `json:"currency,omitempty"`
}
type BillingInfoCurrency struct {
Name string `json:"name,omitempty"`
ShortName string `json:"shortName,omitempty"`
Code string `json:"code,omitempty"`
}
// MgInfo type.
type MgInfo struct {
EndpointURL string `json:"endpointUrl"`
Token string `json:"token"`
}
// CostsResponse type.
type CostsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Costs []Cost `json:"costs,omitempty"`
}
// CostsUploadResponse type.
type CostsUploadResponse struct {
Success bool `json:"success"`
UploadedCosts []int `json:"uploadedCosts,omitempty"`
}
// CostsDeleteResponse type.
type CostsDeleteResponse struct {
Success bool `json:"success"`
Count int `json:"count,omitempty"`
NotRemovedIds []int `json:"notRemovedIds,omitempty"`
}
// CostResponse type.
type CostResponse struct {
Success bool `json:"success"`
Cost *Cost `json:"cost,omitempty"`
}
// FilesResponse type.
type FilesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Files []File `json:"files,omitempty"`
}
// FileUpload response.
type FileUploadResponse struct {
Success bool `json:"success"`
File *File `json:"file,omitempty"`
}
// FileResponse type.
type FileResponse struct {
Success bool `json:"success"`
File *File `json:"file,omitempty"`
}
// CustomFieldsResponse type.
type CustomFieldsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomFields []CustomFields `json:"customFields,omitempty"`
}
// CustomDictionariesResponse type.
type CustomDictionariesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomDictionaries *[]CustomDictionary `json:"customDictionaries,omitempty"`
}
// CustomResponse type.
type CustomResponse struct {
Success bool `json:"success"`
Code string `json:"code,omitempty"`
}
// CustomDictionaryResponse type.
type CustomDictionaryResponse struct {
Success bool `json:"success"`
CustomDictionary *CustomDictionary `json:"CustomDictionary,omitempty"`
}
// CustomFieldResponse type.
type CustomFieldResponse struct {
Success bool `json:"success"`
CustomField CustomFields `json:"customField,omitempty"`
}
// UnitsResponse type.
type UnitsResponse struct {
Success bool `json:"success"`
Units *[]Unit `json:"units,omitempty"`
}
// ErrorResponse should be returned to the one-step connection request in case of failure.
type ErrorResponse struct {
SuccessfulResponse
ErrorMessage string `json:"errorMsg"`
}
// ConnectResponse should be returned to the one-step connection request in case of successful connection.
type ConnectResponse struct {
SuccessfulResponse
AccountURL string `json:"accountUrl"`
}
// ConnectionConfigResponse contains connection configuration for one-step connection.
type ConnectionConfigResponse struct {
SuccessfulResponse
Scopes []string `json:"scopes"`
RegisterURL string `json:"registerUrl"`
}
// NewConnectResponse returns ConnectResponse with the provided account URL.
func NewConnectResponse(accountURL string) ConnectResponse {
return ConnectResponse{
SuccessfulResponse: SuccessfulResponse{Success: true},
AccountURL: accountURL,
}
}
// BonusOperationsResponse type.
type BonusOperationsResponse struct {
Success bool `json:"success"`
Pagination *CursorPagination `json:"pagination,omitempty"`
BonusOperations []BonusOperation `json:"bonusOperations,omitempty"`
}
// AccountBonusOperationsResponse type.
type AccountBonusOperationsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
BonusOperations []BonusOperation `json:"bonusOperations,omitempty"`
}
// ClientIDResponse type.
type ClientIDResponse struct {
ErrorMsg string `json:"errorMsg,omitempty"`
Errors map[string]string `json:"errors,omitempty"`
FailedClientIds []ClientID `json:"failed_client_ids,omitempty"`
Success bool `json:"success"`
}
// SourcesResponse type.
type SourcesResponse struct {
ErrorMsg string `json:"errorMsg,omitempty"`
Errors map[string]string `json:"errors,omitempty"`
FailedSources []Source `json:"failed_sources,omitempty"`
Success bool `json:"success"`
}
// CurrencyResponse type.
type CurrencyResponse struct {
Currencies []Currency `json:"currencies,omitempty"`
Success bool `json:"success"`
}
// CurrencyCreateResponse type.
type CurrencyCreateResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
}
type LoyaltyAccountResponse struct {
SuccessfulResponse
LoyaltyAccount `json:"loyaltyAccount"`
}
type LoyaltyAccountActivateResponse struct {
SuccessfulResponse
LoyaltyAccount `json:"loyaltyAccount"`
Verification SmsVerification `json:"verification,omitempty"`
}
type LoyaltyBonusCreditResponse struct {
SuccessfulResponse
LoyaltyBonus LoyaltyBonus `json:"loyaltyBonus"`
}
type LoyaltyBonusDetailsResponse struct {
SuccessfulResponse
Pagination `json:"pagination"`
Statistic LoyaltyBonusStatisticResponse `json:"statistic"`
Bonuses []BonusDetail `json:"bonuses,omitempty"`
}
type LoyaltyBonusStatisticResponse struct {
TotalAmount float64 `json:"totalAmount"`
}
type LoyaltyAccountsResponse struct {
SuccessfulResponse
Pagination *Pagination `json:"pagination"`
LoyaltyAccounts []LoyaltyAccount `json:"loyaltyAccounts,omitempty"`
}
type LoyaltyCalculateResponse struct {
SuccessfulResponse
Order SerializedLoyaltyOrder `json:"order,omitempty"`
Calculations []LoyaltyCalculation `json:"calculations,omitempty"`
Loyalty SerializedLoyalty `json:"loyalty,omitempty"`
}
type LoyaltiesResponse struct {
SuccessfulResponse
Pagination *Pagination `json:"pagination"`
Loyalties []Loyalty `json:"loyalties,omitempty"`
}
type LoyaltyResponse struct {
SuccessfulResponse
Loyalty Loyalty `json:"loyalty"`
}
type ActionProductsGroupResponse struct {
SuccessfulResponse
ID int `json:"id"`
}
type MGChannelTemplatesResponse struct {
Pagination *Pagination `json:"pagination"`
Templates []MGChannelTemplate `json:"templates"`
SuccessfulResponse
}
type StoreOffersResponse struct {
Pagination *Pagination `json:"pagination"`
SuccessfulResponse
Offers []Offer `json:"offers,omitempty"`
}

View file

@ -1,16 +0,0 @@
package retailcrm
import (
"testing"
"github.com/stretchr/testify/assert"
)
func TestNewConnectResponse(t *testing.T) {
assert.Equal(t, ConnectResponse{
SuccessfulResponse: SuccessfulResponse{
Success: true,
},
AccountURL: "https://example.com",
}, NewConnectResponse("https://example.com"))
}

View file

@ -1,30 +0,0 @@
package retailcrm
import (
"fmt"
"strings"
"time"
)
type SystemTime time.Time
const systemTimeLayout = "2006-01-02 15:04:05"
// UnmarshalJSON parses time.Time from system format.
func (st *SystemTime) UnmarshalJSON(b []byte) (err error) {
s := strings.Trim(string(b), `"`)
nt, err := time.Parse(systemTimeLayout, s)
*st = SystemTime(nt)
return
}
// MarshalJSON will marshal time.Time to system format.
func (st SystemTime) MarshalJSON() ([]byte, error) {
return []byte(st.String()), nil
}
// String returns the time in the custom format.
func (st *SystemTime) String() string {
t := time.Time(*st)
return fmt.Sprintf("%q", t.Format(systemTimeLayout))
}

View file

@ -1,122 +0,0 @@
package retailcrm
import (
"encoding/json"
"errors"
"fmt"
)
const (
// TemplateItemTypeText is a type for text chunk in template.
TemplateItemTypeText uint8 = iota
// TemplateItemTypeVar is a type for variable in template.
TemplateItemTypeVar
QuickReply ButtonType = "QUICK_REPLY"
PhoneNumber ButtonType = "PHONE_NUMBER"
URL ButtonType = "URL"
)
const (
// TemplateVarCustom is a custom variable type.
TemplateVarCustom = "custom"
// TemplateVarName is a name variable type.
TemplateVarName = "name"
// TemplateVarFirstName is a first name variable type.
TemplateVarFirstName = "first_name"
// TemplateVarLastName is a last name variable type.
TemplateVarLastName = "last_name"
)
// templateVarAssoc for checking variable validity, only for internal use.
var templateVarAssoc = map[string]interface{}{
TemplateVarCustom: nil,
TemplateVarName: nil,
TemplateVarFirstName: nil,
TemplateVarLastName: nil,
}
type Text struct {
Parts []TextTemplateItem `json:"parts"`
Example []string `json:"example,omitempty"`
}
type Media struct {
Example string `json:"example,omitempty"`
}
type Header struct {
Text *Text `json:"text,omitempty"`
Document *Media `json:"document,omitempty"`
Image *Media `json:"image,omitempty"`
Video *Media `json:"video,omitempty"`
}
type TemplateItemList []TextTemplateItem
// TextTemplateItem is a part of template.
type TextTemplateItem struct {
Text string
VarType string
Type uint8
}
// MarshalJSON controls how TextTemplateItem will be marshaled into JSON.
func (t TextTemplateItem) MarshalJSON() ([]byte, error) {
switch t.Type {
case TemplateItemTypeText:
return json.Marshal(t.Text)
case TemplateItemTypeVar:
return json.Marshal(map[string]interface{}{
"var": t.VarType,
})
}
return nil, errors.New("unknown TextTemplateItem type")
}
// UnmarshalJSON will correctly unmarshal TextTemplateItem.
func (t *TextTemplateItem) UnmarshalJSON(b []byte) error {
var obj interface{}
err := json.Unmarshal(b, &obj)
if err != nil {
return err
}
switch bodyPart := obj.(type) {
case string:
t.Type = TemplateItemTypeText
t.Text = bodyPart
case map[string]interface{}:
// {} case
if len(bodyPart) == 0 {
t.Type = TemplateItemTypeText
t.Text = "{}"
return nil
}
if varTypeCurr, ok := bodyPart["var"].(string); ok {
if _, ok := templateVarAssoc[varTypeCurr]; !ok {
return fmt.Errorf("invalid placeholder var '%s'", varTypeCurr)
}
t.Type = TemplateItemTypeVar
t.VarType = varTypeCurr
} else {
return errors.New("invalid TextTemplateItem")
}
default:
return errors.New("invalid TextTemplateItem")
}
return nil
}
type ButtonType string
type Button struct {
Type ButtonType `json:"type"`
URL string `json:"url,omitempty"`
Text string `json:"text,omitempty"`
PhoneNumber string `json:"phoneNumber,omitempty"`
Example []string `json:"example,omitempty"`
}

View file

@ -1,565 +0,0 @@
//go:build testutils
// +build testutils
package retailcrm
func getProductsCreate() []ProductCreate {
products := []ProductCreate{
{
CatalogID: 3,
BaseProduct: BaseProduct{
Name: "Product 1",
URL: "https://example.com/p/1",
Article: "p1",
ExternalID: "ext1",
Manufacturer: "man1",
Description: "Description 1",
Popular: true,
Stock: true,
Novelty: true,
Recommended: true,
Active: true,
Markable: true,
},
Groups: []ProductEditGroupInput{{ID: 19}},
},
{
CatalogID: 3,
BaseProduct: BaseProduct{
Name: "Product 2",
URL: "https://example.com/p/2",
Article: "p2",
ExternalID: "ext2",
Manufacturer: "man2",
Description: "Description 2",
Popular: true,
Stock: true,
Novelty: true,
Recommended: true,
Active: true,
Markable: true,
},
Groups: []ProductEditGroupInput{{ID: 19}},
},
}
return products
}
func getProductsCreateResponse() ProductsBatchCreateResponse {
return ProductsBatchCreateResponse{
SuccessfulResponse: SuccessfulResponse{Success: true},
ProcessedProductsCount: 2,
AddedProducts: []int{1, 2},
}
}
func getProductsEdit() []ProductEdit {
products := []ProductEdit{
{
BaseProduct: getProductsCreate()[0].BaseProduct,
ID: 194,
CatalogID: 3,
Site: "second",
},
{
BaseProduct: getProductsCreate()[1].BaseProduct,
ID: 195,
CatalogID: 3,
Site: "second",
},
}
return products
}
func getProductsEditResponse() ProductsBatchEditResponse {
return ProductsBatchEditResponse{
SuccessfulResponse: SuccessfulResponse{Success: true},
ProcessedProductsCount: 2,
NotFoundProducts: nil,
}
}
func getLoyaltyAccountCreate() SerializedCreateLoyaltyAccount {
return SerializedCreateLoyaltyAccount{
SerializedBaseLoyaltyAccount: SerializedBaseLoyaltyAccount{
PhoneNumber: "89151005004",
CustomFields: []interface{}{"dog"},
},
Customer: SerializedEntityCustomer{
ID: 123,
},
}
}
func getLoyaltyAccountCreateResponse() CreateLoyaltyAccountResponse {
return CreateLoyaltyAccountResponse{
SuccessfulResponse: SuccessfulResponse{Success: true},
LoyaltyAccount: LoyaltyAccount{
Active: true,
ID: 13,
PhoneNumber: "89151005004",
LoyaltyLevel: LoyaltyLevel{},
CreatedAt: "2022-11-24 12:39:37",
ActivatedAt: "2022-11-24 12:39:37",
CustomFields: map[string]interface{}{
"animal": "dog",
},
},
}
}
func getLoyaltyAccountEditResponse() EditLoyaltyAccountResponse {
return EditLoyaltyAccountResponse{
SuccessfulResponse: SuccessfulResponse{Success: true},
LoyaltyAccount: LoyaltyAccount{
Active: true,
ID: 13,
PhoneNumber: "89142221020",
LoyaltyLevel: LoyaltyLevel{},
CreatedAt: "2022-11-24 12:39:37",
ActivatedAt: "2022-11-24 12:39:37",
CustomFields: map[string]interface{}{
"animal": "dog",
},
},
}
}
func getLoyaltyAccountResponse() string {
return `{
"success": true,
"loyaltyAccount": {
"active": true,
"id": 13,
"loyalty": {
"id": 2
},
"customer": {
"id": 123,
"customFields": {},
"firstName": "Руслан1",
"lastName": "Ефанов",
"patronymic": ""
},
"phoneNumber": "89142221020",
"amount": 0,
"ordersSum": 0,
"nextLevelSum": 10000,
"level": {
"type": "bonus_percent",
"id": 5,
"name": "Новичок",
"sum": 0,
"privilegeSize": 5,
"privilegeSizePromo": 3
},
"createdAt": "2022-11-24 12:39:37",
"activatedAt": "2022-11-24 12:39:37",
"status": "activated",
"customFields": {
"custom_multiselect": ["test1", "test3"],
"custom_select": "test2",
"custom_integer": 456,
"custom_float": 8.43
}
}
}`
}
func getBonusDetailsResponse() string {
return `{
"success": true,
"pagination": {
"limit": 20,
"totalCount": 41,
"currentPage": 3,
"totalPageCount": 3
},
"statistic": {
"totalAmount": 240
},
"bonuses": [
{
"date": "2022-12-08",
"amount": 240
}
]
}`
}
func getLoyaltyAccountsResponse() string {
return `{
"success": true,
"pagination": {
"limit": 20,
"totalCount": 1,
"currentPage": 1,
"totalPageCount": 1
},
"loyaltyAccounts": [
{
"active": true,
"id": 14,
"loyalty": {
"id": 2
},
"customer": {
"id": 109,
"firstName": "Казимир",
"lastName": "Эльбрусов"
},
"phoneNumber": "89185556363",
"amount": 0,
"ordersSum": 0,
"nextLevelSum": 10000,
"level": {
"type": "bonus_percent",
"id": 5,
"name": "Новичок",
"sum": 0,
"privilegeSize": 5,
"privilegeSizePromo": 3
},
"createdAt": "2022-12-07 15:27:04",
"activatedAt": "2022-12-07 15:27:04",
"status": "activated"
}
]
}`
}
func getLoyaltyCalculateReq() LoyaltyCalculateRequest {
return LoyaltyCalculateRequest{
Site: "main",
Order: Order{
PrivilegeType: "loyalty_level",
Customer: &Customer{
ID: 123,
},
Items: []OrderItem{
{
InitialPrice: 10000,
Quantity: 1,
Offer: Offer{ID: 214},
PriceType: &PriceType{Code: "base"},
},
},
},
Bonuses: 10,
}
}
func getLoyaltyCalculateResponse() string {
return `{
"success": true,
"order": {
"bonusesCreditTotal": 999,
"bonusesChargeTotal": 10,
"privilegeType": "loyalty_level",
"totalSumm": 9990,
"loyaltyAccount": {
"id": 13,
"amount": 240
},
"loyaltyLevel": {
"id": 6,
"name": "Любитель"
},
"customer": {
"id": 123,
"personalDiscount": 0
},
"delivery": {
"cost": 0
},
"site": "main",
"items": [
{
"bonusesChargeTotal": 10,
"bonusesCreditTotal": 999,
"priceType": {
"code": "base"
},
"initialPrice": 10000,
"discounts": [
{
"type": "bonus_charge",
"amount": 10
}
],
"discountTotal": 10,
"prices": [
{
"price": 9990,
"quantity": 1
}
],
"quantity": 1,
"offer": {
"xmlId": "696999ed-bc8d-4d0f-9627-527acf7b1d57"
}
}
]
},
"calculations": [
{
"privilegeType": "loyalty_level",
"discount": 10,
"creditBonuses": 999,
"maxChargeBonuses": 240,
"maximum": true
},
{
"privilegeType": "none",
"discount": 10,
"creditBonuses": 0,
"maxChargeBonuses": 240,
"maximum": false
}
],
"loyalty": {
"name": "Бонусная программа",
"chargeRate": 1
}
}`
}
func getLoyaltiesResponse() string {
return `{
"success": true,
"pagination": {
"limit": 20,
"totalCount": 1,
"currentPage": 1,
"totalPageCount": 1
},
"loyalties": [
{
"levels": [
{
"type": "bonus_percent",
"id": 5,
"name": "Новичок",
"sum": 0,
"privilegeSize": 5,
"privilegeSizePromo": 3
},
{
"type": "bonus_percent",
"id": 6,
"name": "Любитель",
"sum": 10000,
"privilegeSize": 10,
"privilegeSizePromo": 5
},
{
"type": "bonus_percent",
"id": 7,
"name": "Продвинутый покупатель",
"sum": 25000,
"privilegeSize": 15,
"privilegeSizePromo": 7
},
{
"type": "bonus_percent",
"id": 8,
"name": "Мастер шоппинга",
"sum": 50000,
"privilegeSize": 20,
"privilegeSizePromo": 10
}
],
"active": true,
"blocked": false,
"id": 2,
"name": "Бонусная программа",
"confirmSmsCharge": false,
"confirmSmsRegistration": false,
"createdAt": "2022-01-18 15:40:22",
"activatedAt": "2022-12-08 12:05:45"
}
]
}`
}
func getLoyaltyResponse() string {
return `{
"success": true,
"loyalty": {
"levels": [
{
"type": "bonus_percent",
"id": 5,
"name": "Новичок",
"sum": 0,
"privilegeSize": 5,
"privilegeSizePromo": 3
},
{
"type": "bonus_percent",
"id": 6,
"name": "Любитель",
"sum": 10000,
"privilegeSize": 10,
"privilegeSizePromo": 5
},
{
"type": "bonus_percent",
"id": 7,
"name": "Продвинутый покупатель",
"sum": 25000,
"privilegeSize": 15,
"privilegeSizePromo": 7
},
{
"type": "bonus_percent",
"id": 8,
"name": "Мастер шоппинга",
"sum": 50000,
"privilegeSize": 20,
"privilegeSizePromo": 10
}
],
"active": true,
"blocked": false,
"id": 2,
"name": "Бонусная программа",
"confirmSmsCharge": false,
"confirmSmsRegistration": false,
"createdAt": "2022-01-18 15:40:22",
"activatedAt": "2022-12-08 12:05:45"
}
}`
}
func getMGTemplatesResponse() string {
return `{
"success": true,
"pagination": {
"limit": 10,
"totalCount": 100,
"currentPage": 5,
"totalPageCount": 10
},
"templates": [
{
"id": 1,
"externalId": 0,
"channel": {
"allowedSendByPhone": false,
"id": 1,
"externalId": 1,
"type": "fbmessenger",
"active": true,
"name": "fbmessenger"
},
"code": "namespace#NAMEAAA#ru",
"name": "NAMEAAA",
"active": true,
"template": [
"Text_0",
{
"var": "custom"
}
],
"templateExample": ["Text_1"],
"namespace": "namespace_0",
"lang": "en",
"category": "test_0",
"header": {
"text": {
"parts": [
"JABAAA",
{
"var": "custom"
}
],
"example": [
"AAAAAA"
]
},
"image": {
"example": "https://example.com/file/123.png"
},
"document": {
"example": "https://example.com/file/123.pdf"
},
"video": {
"example": "https://example.com/file/123.mp4"
}
},
"footer": "footer_0",
"buttons": [
{
"type": "PHONE_NUMBER",
"text": "your-phone-button-text",
"phoneNumber": "+79895553535"
},
{
"type": "QUICK_REPLY",
"text": "Yes"
},
{
"type": "URL",
"url": "https://example.com/file/{{1}}",
"text": "button",
"example": [
"https://www.website.com/dynamic-url-example"
]
}
],
"verificationStatus": "APPROVED"
}
]
}`
}
func getMGTemplatesForEdit() string {
return `[{"header":{"text":{"parts":["Hello,",{"var":"custom"}],"example":["Henry"]},"document":{"example":"https://example.com/file/123.pdf"},"image":{"example":"https://example.com/file/123.png"},"video":{"example":"https://example.com/file/123.mp4"}},"lang":"en","category":"test_0","code":"namespace#name_0#ru","name":"name_0","namespace":"namespace","footer":"footer_0","verificationStatus":"REJECTED","template":["Text_0",{"var":"custom"}],"buttons":[{"type":"PHONE_NUMBER","text":"your-phone-button-text","phoneNumber":"+79895553535"},{"type":"QUICK_REPLY","text":"Yes"},{"type":"URL","url":"https://example.com/file/{{1}}","text":"button","example":["https://www.website.com/dynamic-url-example"]}],"templateExample":["WIU"],"id":1,"externalId":10,"mgChannelId":110,"active":true}]`
}
func getStoreOfferResponse() string {
return `{
"success": true,
"pagination": {
"limit": 20,
"totalCount": 1,
"currentPage": 1,
"totalPageCount": 1
},
"offers": [
{
"images": [
"https://s3-s1.retailcrm.tech/ru-central1/retailcrm/dev-vega-d32aea7f9a5bc26eba6ad986077cea03/product/65a92fa0bb737-test.jpeg"
],
"id": 76,
"site": "main",
"name": "Название\nПеревод строки",
"article": "Артикул",
"product": {
"type": "product",
"catalogId": 2,
"id": 222
},
"prices": [
{
"priceType": "base",
"price": 10000,
"ordering": 991,
"currency": "RUB"
}
],
"purchasePrice": 10,
"quantity": 5,
"active": true,
"unit": {
"code": "pc",
"name": "Штука",
"sym": "шт."
}
}
]
}`
}

1719
types.go

File diff suppressed because it is too large Load diff

View file

@ -1,55 +0,0 @@
package retailcrm
import (
"encoding/json"
"reflect"
"testing"
)
func TestClient_OrderDeliveryData(t *testing.T) {
d := OrderDeliveryData{
OrderDeliveryDataBasic: OrderDeliveryDataBasic{
"track",
"status",
"address",
"type",
},
}
data, _ := json.Marshal(d)
expectedStr := `{"payerType":"type","pickuppointAddress":"address","status":"status","trackNumber":"track"}`
if string(data) != expectedStr {
t.Errorf("Marshaled: %s\nExpected: %s\n", data, expectedStr)
}
d.AdditionalFields = map[string]interface{}{
"customFirst": "one",
"customSecond": "two",
}
data, _ = json.Marshal(d)
expectedStr = `{"customFirst":"one","customSecond":"two","payerType":"type","pickuppointAddress":"address","status":"status","trackNumber":"track"}`
if string(data) != expectedStr {
t.Errorf("Marshaled: %s\nExpected: %s\n", data, expectedStr)
}
d = OrderDeliveryData{}
json.Unmarshal(data, &d)
expected := OrderDeliveryData{
OrderDeliveryDataBasic: OrderDeliveryDataBasic{
"track",
"status",
"address",
"type",
},
AdditionalFields: map[string]interface{}{
"customFirst": "one",
"customSecond": "two",
},
}
eq := reflect.DeepEqual(expected, d)
if eq != true {
t.Errorf("Unmarshaled: %#v\nExpected: %#v\n", d, expected)
}
}

5618
v5/client.go Normal file

File diff suppressed because it is too large Load diff

File diff suppressed because it is too large Load diff

View file

@ -1,6 +1,6 @@
package retailcrm package v5
// CustomersFilter type. // CustomersFilter type
type CustomersFilter struct { type CustomersFilter struct {
Ids []string `url:"ids,omitempty,brackets"` Ids []string `url:"ids,omitempty,brackets"`
ExternalIds []string `url:"externalIds,omitempty,brackets"` ExternalIds []string `url:"externalIds,omitempty,brackets"`
@ -57,7 +57,7 @@ type CustomersFilter struct {
CustomFields map[string]string `url:"customFields,omitempty,brackets"` CustomFields map[string]string `url:"customFields,omitempty,brackets"`
} }
// CorporateCustomersFilter type. // CorporateCustomersFilter type
type CorporateCustomersFilter struct { type CorporateCustomersFilter struct {
ContragentName string `url:"contragentName,omitempty"` ContragentName string `url:"contragentName,omitempty"`
ContragentInn string `url:"contragentInn,omitempty"` ContragentInn string `url:"contragentInn,omitempty"`
@ -99,7 +99,7 @@ type CorporateCustomersFilter struct {
CustomFields map[string]string `url:"customFields,omitempty,brackets"` CustomFields map[string]string `url:"customFields,omitempty,brackets"`
} }
// CorporateCustomersNotesFilter type. // CorporateCustomersNotesFilter type
type CorporateCustomersNotesFilter struct { type CorporateCustomersNotesFilter struct {
Ids []string `url:"ids,omitempty,brackets"` Ids []string `url:"ids,omitempty,brackets"`
CustomerIds []string `url:"ids,omitempty,brackets"` CustomerIds []string `url:"ids,omitempty,brackets"`
@ -110,7 +110,7 @@ type CorporateCustomersNotesFilter struct {
CreatedAtTo string `url:"createdAtTo,omitempty"` CreatedAtTo string `url:"createdAtTo,omitempty"`
} }
// CorporateCustomerAddressesFilter type. // CorporateCustomerAddressesFilter type
type CorporateCustomerAddressesFilter struct { type CorporateCustomerAddressesFilter struct {
Ids []string `url:"ids,omitempty,brackets"` Ids []string `url:"ids,omitempty,brackets"`
Name string `url:"name,omitempty"` Name string `url:"name,omitempty"`
@ -118,13 +118,13 @@ type CorporateCustomerAddressesFilter struct {
Region string `url:"region,omitempty"` Region string `url:"region,omitempty"`
} }
// IdentifiersPairFilter type. // IdentifiersPairFilter type
type IdentifiersPairFilter struct { type IdentifiersPairFilter struct {
Ids []string `url:"ids,omitempty,brackets"` Ids []string `url:"ids,omitempty,brackets"`
ExternalIds []string `url:"externalIds,omitempty,brackets"` ExternalIds []string `url:"externalIds,omitempty,brackets"`
} }
// CustomersHistoryFilter type. // CustomersHistoryFilter type
type CustomersHistoryFilter struct { type CustomersHistoryFilter struct {
CustomerID int `url:"customerId,omitempty"` CustomerID int `url:"customerId,omitempty"`
SinceID int `url:"sinceId,omitempty"` SinceID int `url:"sinceId,omitempty"`
@ -133,7 +133,7 @@ type CustomersHistoryFilter struct {
EndDate string `url:"endDate,omitempty"` EndDate string `url:"endDate,omitempty"`
} }
// CorporateCustomersHistoryFilter type. // CorporateCustomersHistoryFilter type
type CorporateCustomersHistoryFilter struct { type CorporateCustomersHistoryFilter struct {
CustomerID int `url:"customerId,omitempty"` CustomerID int `url:"customerId,omitempty"`
SinceID int `url:"sinceId,omitempty"` SinceID int `url:"sinceId,omitempty"`
@ -143,7 +143,7 @@ type CorporateCustomersHistoryFilter struct {
EndDate string `url:"endDate,omitempty"` EndDate string `url:"endDate,omitempty"`
} }
// OrdersFilter type. // OrdersFilter type
type OrdersFilter struct { type OrdersFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
ExternalIds []string `url:"externalIds,omitempty,brackets"` ExternalIds []string `url:"externalIds,omitempty,brackets"`
@ -199,7 +199,6 @@ type OrdersFilter struct {
PaymentStatuses []string `url:"paymentStatuses,omitempty,brackets"` PaymentStatuses []string `url:"paymentStatuses,omitempty,brackets"`
PaymentTypes []string `url:"paymentTypes,omitempty,brackets"` PaymentTypes []string `url:"paymentTypes,omitempty,brackets"`
DeliveryTypes []string `url:"deliveryTypes,omitempty,brackets"` DeliveryTypes []string `url:"deliveryTypes,omitempty,brackets"`
DeliveryServices []string `url:"deliveryServices,omitempty,brackets"`
OrderMethods []string `url:"orderMethods,omitempty,brackets"` OrderMethods []string `url:"orderMethods,omitempty,brackets"`
ShipmentStores []string `url:"shipmentStores,omitempty,brackets"` ShipmentStores []string `url:"shipmentStores,omitempty,brackets"`
Couriers []string `url:"couriers,omitempty,brackets"` Couriers []string `url:"couriers,omitempty,brackets"`
@ -208,8 +207,6 @@ type OrdersFilter struct {
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
CreatedAtFrom string `url:"createdAtFrom,omitempty"` CreatedAtFrom string `url:"createdAtFrom,omitempty"`
CreatedAtTo string `url:"createdAtTo,omitempty"` CreatedAtTo string `url:"createdAtTo,omitempty"`
PaidAtFrom string `url:"paidAtFrom,omitempty"`
PaidAtTo string `url:"paidAtTo,omitempty"`
FullPaidAtFrom string `url:"fullPaidAtFrom,omitempty"` FullPaidAtFrom string `url:"fullPaidAtFrom,omitempty"`
FullPaidAtTo string `url:"fullPaidAtTo,omitempty"` FullPaidAtTo string `url:"fullPaidAtTo,omitempty"`
DeliveryDateFrom string `url:"deliveryDateFrom,omitempty"` DeliveryDateFrom string `url:"deliveryDateFrom,omitempty"`
@ -237,7 +234,7 @@ type OrdersFilter struct {
CustomFields map[string]string `url:"customFields,omitempty,brackets"` CustomFields map[string]string `url:"customFields,omitempty,brackets"`
} }
// OrdersHistoryFilter type. // OrdersHistoryFilter type
type OrdersHistoryFilter struct { type OrdersHistoryFilter struct {
OrderID int `url:"orderId,omitempty"` OrderID int `url:"orderId,omitempty"`
SinceID int `url:"sinceId,omitempty"` SinceID int `url:"sinceId,omitempty"`
@ -246,7 +243,7 @@ type OrdersHistoryFilter struct {
EndDate string `url:"endDate,omitempty"` EndDate string `url:"endDate,omitempty"`
} }
// UsersFilter type. // UsersFilter type
type UsersFilter struct { type UsersFilter struct {
Email string `url:"email,omitempty"` Email string `url:"email,omitempty"`
Status string `url:"status,omitempty"` Status string `url:"status,omitempty"`
@ -259,7 +256,7 @@ type UsersFilter struct {
Groups []string `url:"groups,omitempty,brackets"` Groups []string `url:"groups,omitempty,brackets"`
} }
// TasksFilter type. // TasksFilter type
type TasksFilter struct { type TasksFilter struct {
OrderNumber string `url:"orderNumber,omitempty"` OrderNumber string `url:"orderNumber,omitempty"`
Status string `url:"status,omitempty"` Status string `url:"status,omitempty"`
@ -271,7 +268,7 @@ type TasksFilter struct {
Performers []int `url:"performers,omitempty,brackets"` Performers []int `url:"performers,omitempty,brackets"`
} }
// NotesFilter type. // NotesFilter type
type NotesFilter struct { type NotesFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
CustomerIds []int `url:"customerIds,omitempty,brackets"` CustomerIds []int `url:"customerIds,omitempty,brackets"`
@ -282,7 +279,7 @@ type NotesFilter struct {
CreatedAtTo string `url:"createdAtTo,omitempty"` CreatedAtTo string `url:"createdAtTo,omitempty"`
} }
// SegmentsFilter type. // SegmentsFilter type
type SegmentsFilter struct { type SegmentsFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
Active int `url:"active,omitempty"` Active int `url:"active,omitempty"`
@ -294,7 +291,7 @@ type SegmentsFilter struct {
DateTo string `url:"dateTo,omitempty"` DateTo string `url:"dateTo,omitempty"`
} }
// PacksFilter type. // PacksFilter type
type PacksFilter struct { type PacksFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
Stores []string `url:"stores,omitempty"` Stores []string `url:"stores,omitempty"`
@ -309,7 +306,7 @@ type PacksFilter struct {
DeliveryNoteNumber string `url:"deliveryNoteNumber,omitempty"` DeliveryNoteNumber string `url:"deliveryNoteNumber,omitempty"`
} }
// InventoriesFilter type. // InventoriesFilter type
type InventoriesFilter struct { type InventoriesFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
ProductExternalID string `url:"productExternalId,omitempty"` ProductExternalID string `url:"productExternalId,omitempty"`
@ -322,7 +319,7 @@ type InventoriesFilter struct {
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
} }
// ProductsGroupsFilter type. // ProductsGroupsFilter type
type ProductsGroupsFilter struct { type ProductsGroupsFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
@ -330,7 +327,7 @@ type ProductsGroupsFilter struct {
ParentGroupID string `url:"parentGroupId,omitempty"` ParentGroupID string `url:"parentGroupId,omitempty"`
} }
// ProductsFilter type. // ProductsFilter type
type ProductsFilter struct { type ProductsFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
OfferIds []int `url:"offerIds,omitempty,brackets"` OfferIds []int `url:"offerIds,omitempty,brackets"`
@ -352,21 +349,20 @@ type ProductsFilter struct {
ExternalID string `url:"externalId,omitempty"` ExternalID string `url:"externalId,omitempty"`
Manufacturer string `url:"manufacturer,omitempty"` Manufacturer string `url:"manufacturer,omitempty"`
URL string `url:"url,omitempty"` URL string `url:"url,omitempty"`
URLLike string `url:"urlLike,omitempty"`
PriceType string `url:"priceType,omitempty"` PriceType string `url:"priceType,omitempty"`
OfferExternalID string `url:"offerExternalId,omitempty"` OfferExternalID string `url:"offerExternalId,omitempty"`
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
Properties map[string]string `url:"properties,omitempty,brackets"` Properties map[string]string `url:"properties,omitempty,brackets"`
} }
// ProductsPropertiesFilter type. // ProductsPropertiesFilter type
type ProductsPropertiesFilter struct { type ProductsPropertiesFilter struct {
Code string `url:"code,omitempty"` Code string `url:"code,omitempty"`
Name string `url:"name,omitempty"` Name string `url:"name,omitempty"`
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
} }
// ShipmentFilter type. // ShipmentFilter type
type ShipmentFilter struct { type ShipmentFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
ExternalID string `url:"externalId,omitempty"` ExternalID string `url:"externalId,omitempty"`
@ -379,27 +375,27 @@ type ShipmentFilter struct {
Statuses []string `url:"statuses,omitempty,brackets"` Statuses []string `url:"statuses,omitempty,brackets"`
} }
// CostsFilter type. // CostsFilter type
type CostsFilter struct { type CostsFilter struct {
MinSumm int `url:"minSumm,omitempty"` MinSumm string `url:"minSumm,omitempty"`
MaxSumm int `url:"maxSumm,omitempty"` MaxSumm string `url:"maxSumm,omitempty"`
OrderNumber string `url:"orderNumber,omitempty"` OrderNumber string `url:"orderNumber,omitempty"`
Comment string `url:"orderNumber,omitempty"` Comment string `url:"orderNumber,omitempty"`
IDs []int `url:"ids,omitempty,brackets"` Ids []string `url:"ids,omitempty,brackets"`
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
CreatedBy []int `url:"createdBy,omitempty,brackets"` CreatedBy []string `url:"createdBy,omitempty,brackets"`
CostGroups []string `url:"costGroups,omitempty,brackets"` CostGroups []string `url:"costGroups,omitempty,brackets"`
CostItems []string `url:"costItems,omitempty,brackets"` CostItems []string `url:"costItems,omitempty,brackets"`
Users []int `url:"users,omitempty,brackets"` Users []string `url:"users,omitempty,brackets"`
DateFrom string `url:"dateFrom,omitempty"` DateFrom string `url:"dateFrom,omitempty"`
DateTo string `url:"dateTo,omitempty"` DateTo string `url:"dateTo,omitempty"`
CreatedAtFrom string `url:"createdAtFrom,omitempty"` CreatedAtFrom string `url:"createdAtFrom,omitempty"`
CreatedAtTo string `url:"createdAtTo,omitempty"` CreatedAtTo string `url:"createdAtTo,omitempty"`
OrderIDs []int `url:"orderIds,omitempty,brackets"` OrderIds []string `url:"orderIds,omitempty,brackets"`
OrderExternalIDs []string `url:"orderExternalIds,omitempty,brackets"` OrderExternalIds []string `url:"orderIds,omitempty,brackets"`
} }
// FilesFilter type. // FilesFilter type
type FilesFilter struct { type FilesFilter struct {
Ids []int `url:"ids,omitempty,brackets"` Ids []int `url:"ids,omitempty,brackets"`
OrderIds []int `url:"orderIds,omitempty,brackets"` OrderIds []int `url:"orderIds,omitempty,brackets"`
@ -416,7 +412,7 @@ type FilesFilter struct {
Sites []string `url:"sites,omitempty,brackets"` Sites []string `url:"sites,omitempty,brackets"`
} }
// CustomFieldsFilter type. // CustomFieldsFilter type
type CustomFieldsFilter struct { type CustomFieldsFilter struct {
Name string `url:"name,omitempty"` Name string `url:"name,omitempty"`
Code string `url:"code,omitempty"` Code string `url:"code,omitempty"`
@ -426,72 +422,8 @@ type CustomFieldsFilter struct {
DisplayArea string `url:"displayArea,omitempty"` DisplayArea string `url:"displayArea,omitempty"`
} }
// CustomDictionariesFilter type. // CustomDictionariesFilter type
type CustomDictionariesFilter struct { type CustomDictionariesFilter struct {
Name string `url:"name,omitempty"` Name string `url:"name,omitempty"`
Code string `url:"code,omitempty"` Code string `url:"code,omitempty"`
} }
// BonusOperationsFilter type.
type BonusOperationsFilter struct {
Loyalties []int `url:"loyalties,omitempty,brackets"`
}
type AccountBonusOperationsFilter struct {
CreatedAtFrom string `url:"createdAtFrom,omitempty"`
CreatedAtTo string `url:"createdAtTo,omitempty"`
}
type LoyaltyBonusAPIFilterType struct {
Date string `url:"date,omitempty"`
}
type LoyaltyAccountAPIFilter struct {
ID string `url:"id,omitempty"`
Status string `url:"status,,omitempty"`
Customer string `url:"customer,omitempty"`
MinOrderSum string `url:"minOrdersSum,omitempty"`
MaxOrderSum string `url:"maxOrdersSum,omitempty"`
MinAmount string `url:"minAmount,omitempty"`
MaxAmount string `url:"maxAmount,omitempty"`
PhoneNumber string `url:"phoneNumber,omitempty"`
CardNumber string `url:"cardNumber,omitempty"`
Ids []int `url:"ids,omitempty,brackets"`
Loyalties []int `url:"loyalties,omitempty,brackets"`
Sites []string `url:"sites,omitempty,brackets"`
Level int `url:"level,omitempty"`
CreatedAtFrom string `url:"createdAtFrom,omitempty"`
CreatedAtTo string `url:"createdAtTo,omitempty"`
BurnDateFrom string `url:"burnDateFrom,omitempty"`
BurnDateTo string `url:"burnDateTo,omitempty"`
CustomFields []string `url:"customFields,omitempty,brackets"`
CustomerID string `url:"customerId,omitempty"`
CustomerExternalID string `url:"customerExternalId,omitempty"`
}
type LoyaltyAPIFilter struct {
Active *int `url:"active,omitempty"`
Blocked *int `url:"blocked,omitempty"`
Ids []int `url:"ids,omitempty,brackets"`
Sites []string `url:"sites,omitempty,brackets"`
}
type OffersFilter struct {
Ids []int `url:"ids,omitempty,brackets"`
Active *int `url:"active,omitempty"`
}
type SiteFilter struct {
// SiteBy contains information about what is betrayed site id or site code.
// id|code, default is code.
SiteBy string `url:"siteBy,omitempty"`
}
type GetCartFilter struct {
// SiteBy contains information about what is betrayed site id or site code.
// id|code, default is code.
SiteBy string `url:"siteBy,omitempty"`
// By contains information about what is betrayed: customer id or customer externalId.
// id|externalId, default is externalId.
By string `url:"by,omitempty"`
}

View file

@ -1,39 +1,33 @@
package retailcrm package v5
import ( // CustomerRequest type
"crypto/hmac"
"crypto/sha256"
"encoding/hex"
)
// CustomerRequest type.
type CustomerRequest struct { type CustomerRequest struct {
By string `url:"by,omitempty"` By string `url:"by,omitempty"`
Site string `url:"site,omitempty"` Site string `url:"site,omitempty"`
} }
// CustomersRequest type. // CustomersRequest type
type CustomersRequest struct { type CustomersRequest struct {
Filter CustomersFilter `url:"filter,omitempty"` Filter CustomersFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CorporateCustomersRequest type. // CorporateCustomersRequest type
type CorporateCustomersRequest struct { type CorporateCustomersRequest struct {
Filter CorporateCustomersFilter `url:"filter,omitempty"` Filter CorporateCustomersFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CorporateCustomersNotesRequest type. // CorporateCustomersNotesRequest type
type CorporateCustomersNotesRequest struct { type CorporateCustomersNotesRequest struct {
Filter CorporateCustomersNotesFilter `url:"filter,omitempty"` Filter CorporateCustomersNotesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CorporateCustomerAddressesRequest type. // CorporateCustomerAddressesRequest type
type CorporateCustomerAddressesRequest struct { type CorporateCustomerAddressesRequest struct {
Filter CorporateCustomerAddressesFilter `url:"filter,omitempty"` Filter CorporateCustomerAddressesFilter `url:"filter,omitempty"`
By string `url:"by,omitempty"` By string `url:"by,omitempty"`
@ -42,7 +36,7 @@ type CorporateCustomerAddressesRequest struct {
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// IdentifiersPairRequest type. // IdentifiersPairRequest type
type IdentifiersPairRequest struct { type IdentifiersPairRequest struct {
Filter IdentifiersPairFilter `url:"filter,omitempty"` Filter IdentifiersPairFilter `url:"filter,omitempty"`
By string `url:"by,omitempty"` By string `url:"by,omitempty"`
@ -51,282 +45,173 @@ type IdentifiersPairRequest struct {
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CustomersUploadRequest type. // CustomersUploadRequest type
type CustomersUploadRequest struct { type CustomersUploadRequest struct {
Customers []Customer `url:"customers,omitempty,brackets"` Customers []Customer `url:"customers,omitempty,brackets"`
Site string `url:"site,omitempty"` Site string `url:"site,omitempty"`
} }
// CustomersHistoryRequest type. // CustomersHistoryRequest type
type CustomersHistoryRequest struct { type CustomersHistoryRequest struct {
Filter CustomersHistoryFilter `url:"filter,omitempty"` Filter CustomersHistoryFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CorporateCustomersHistoryRequest type. // CorporateCustomersHistoryRequest type
type CorporateCustomersHistoryRequest struct { type CorporateCustomersHistoryRequest struct {
Filter CorporateCustomersHistoryFilter `url:"filter,omitempty"` Filter CorporateCustomersHistoryFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// OrderRequest type. // OrderRequest type
type OrderRequest struct { type OrderRequest struct {
By string `url:"by,omitempty"` By string `url:"by,omitempty"`
Site string `url:"site,omitempty"` Site string `url:"site,omitempty"`
} }
// OrdersRequest type. // OrdersRequest type
type OrdersRequest struct { type OrdersRequest struct {
Filter OrdersFilter `url:"filter,omitempty"` Filter OrdersFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// OrdersStatusesRequest type. // OrdersStatusesRequest type
type OrdersStatusesRequest struct { type OrdersStatusesRequest struct {
IDs []int `url:"ids,omitempty,brackets"` IDs []int `url:"ids,omitempty,brackets"`
ExternalIDs []string `url:"externalIds,omitempty,brackets"` ExternalIDs []string `url:"externalIds,omitempty,brackets"`
} }
// OrdersUploadRequest type. // OrdersUploadRequest type
type OrdersUploadRequest struct { type OrdersUploadRequest struct {
Orders []Order `url:"orders,omitempty,brackets"` Orders []Order `url:"orders,omitempty,brackets"`
Site string `url:"site,omitempty"` Site string `url:"site,omitempty"`
} }
// OrdersHistoryRequest type. // OrdersHistoryRequest type
type OrdersHistoryRequest struct { type OrdersHistoryRequest struct {
Filter OrdersHistoryFilter `url:"filter,omitempty"` Filter OrdersHistoryFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// PacksRequest type. // PacksRequest type
type PacksRequest struct { type PacksRequest struct {
Filter PacksFilter `url:"filter,omitempty"` Filter PacksFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// PacksHistoryRequest type. // PacksHistoryRequest type
type PacksHistoryRequest struct { type PacksHistoryRequest struct {
Filter OrdersHistoryFilter `url:"filter,omitempty"` Filter OrdersHistoryFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// UsersRequest type. // UsersRequest type
type UsersRequest struct { type UsersRequest struct {
Filter UsersFilter `url:"filter,omitempty"` Filter UsersFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// UserGroupsRequest type. // UserGroupsRequest type
type UserGroupsRequest struct { type UserGroupsRequest struct {
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// TasksRequest type. // TasksRequest type
type TasksRequest struct { type TasksRequest struct {
Filter TasksFilter `url:"filter,omitempty"` Filter TasksFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// NotesRequest type. // NotesRequest type
type NotesRequest struct { type NotesRequest struct {
Filter NotesFilter `url:"filter,omitempty"` Filter NotesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// SegmentsRequest type. // SegmentsRequest type
type SegmentsRequest struct { type SegmentsRequest struct {
Filter SegmentsFilter `url:"filter,omitempty"` Filter SegmentsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// InventoriesRequest type. // InventoriesRequest type
type InventoriesRequest struct { type InventoriesRequest struct {
Filter InventoriesFilter `url:"filter,omitempty"` Filter InventoriesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// ProductsGroupsRequest type. // ProductsGroupsRequest type
type ProductsGroupsRequest struct { type ProductsGroupsRequest struct {
Filter ProductsGroupsFilter `url:"filter,omitempty"` Filter ProductsGroupsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// ProductsRequest type. // ProductsRequest type
type ProductsRequest struct { type ProductsRequest struct {
Filter ProductsFilter `url:"filter,omitempty"` Filter ProductsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// ProductsPropertiesRequest type. // ProductsPropertiesRequest type
type ProductsPropertiesRequest struct { type ProductsPropertiesRequest struct {
Filter ProductsPropertiesFilter `url:"filter,omitempty"` Filter ProductsPropertiesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// DeliveryTrackingRequest type. // DeliveryTrackingRequest type
type DeliveryTrackingRequest struct { type DeliveryTrackingRequest struct {
DeliveryID string `json:"deliveryId,omitempty"` DeliveryID string `url:"deliveryId,omitempty"`
TrackNumber string `json:"trackNumber,omitempty"` TrackNumber string `url:"trackNumber,omitempty"`
History []DeliveryHistoryRecord `json:"history,omitempty"` History []DeliveryHistoryRecord `url:"history,omitempty,brackets"`
ExtraData map[string]string `json:"extraData,omitempty"` ExtraData map[string]string `url:"extraData,omitempty,brackets"`
} }
// DeliveryShipmentsRequest type. // DeliveryShipmentsRequest type
type DeliveryShipmentsRequest struct { type DeliveryShipmentsRequest struct {
Filter ShipmentFilter `url:"filter,omitempty"` Filter ShipmentFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// ClearCartRequest type. // CostsRequest type
type ClearCartRequest struct {
ClearedAt string `url:"clearedAt,omitempty"`
Customer CartCustomer `url:"customer,omitempty"`
Order ClearCartOrder `url:"order,omitempty"`
}
// SetCartRequest type.
type SetCartRequest struct {
ExternalID string `url:"externalId,omitempty"`
DroppedAt string `url:"droppedAt,omitempty"`
Link string `url:"link,omitempty"`
Customer CartCustomer `url:"customer,omitempty"`
Items []SetCartItem `url:"items,omitempty"`
}
// CostsRequest type.
type CostsRequest struct { type CostsRequest struct {
Filter CostsFilter `url:"filter,omitempty"` Filter CostsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// FilesRequest type. // FilesRequest type
type FilesRequest struct { type FilesRequest struct {
Filter FilesFilter `url:"filter,omitempty"` Filter FilesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CustomFieldsRequest type. // CustomFieldsRequest type
type CustomFieldsRequest struct { type CustomFieldsRequest struct {
Filter CustomFieldsFilter `url:"filter,omitempty"` Filter CustomFieldsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// CustomDictionariesRequest type. // CustomDictionariesRequest type
type CustomDictionariesRequest struct { type CustomDictionariesRequest struct {
Filter CustomDictionariesFilter `url:"filter,omitempty"` Filter CustomDictionariesFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"` Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"` Page int `url:"page,omitempty"`
} }
// ConnectRequest contains information about the system connection that is requested to be created.
type ConnectRequest struct {
// Token is used to verify the request. Do not use directly; use Verify instead.
Token string `json:"token"`
// APIKey that was generated for the module.
APIKey string `json:"apiKey"`
// URL of the system. Do not use directly; use SystemURL instead.
URL string `json:"systemUrl"`
}
// BonusOperationsRequest type.
type BonusOperationsRequest struct {
Filter BonusOperationsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"`
Cursor string `url:"cursor,omitempty"`
}
// AccountBonusOperationsRequest type.
type AccountBonusOperationsRequest struct {
Filter AccountBonusOperationsFilter `url:"filter,omitempty"`
Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"`
}
type LoyaltyBonusCreditRequest struct {
Amount float64 `url:"amount"`
ActivationDate string `url:"activationDate,omitempty"`
ExpiredDate string `url:"expireDate,omitempty"`
Comment string `url:"comment,omitempty"`
}
type LoyaltyBonusStatusDetailsRequest struct {
Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"`
Filter LoyaltyBonusAPIFilterType `url:"filter,omitempty"`
}
type LoyaltyAccountsRequest struct {
Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"`
Filter LoyaltyAccountAPIFilter `url:"filter,omitempty"`
}
type LoyaltyCalculateRequest struct {
Site string
Order Order
Bonuses float32
}
type LoyaltiesRequest struct {
Limit int `url:"limit,omitempty"`
Page int `url:"page,omitempty"`
Filter LoyaltyAPIFilter `url:"filter,omitempty"`
}
type NotificationsSendRequest struct {
UserGroups []UserGroupType `json:"userGroups,omitempty"`
Type NotificationType `json:"type"`
Message string `json:"message"`
UserIDs []string `json:"userIds,omitempty"`
}
type EditMGChannelTemplateRequest struct {
Templates []MGChannelTemplate `json:"templates"`
Removed []int `json:"removed"`
}
// SystemURL returns system URL from the connection request without trailing slash.
func (r ConnectRequest) SystemURL() string {
if r.URL == "" {
return ""
}
if r.URL[len(r.URL)-1:] == "/" {
return r.URL[:len(r.URL)-1]
}
return r.URL
}
// Verify returns true if connection request is legitimate. Application secret should be provided to this method.
func (r ConnectRequest) Verify(secret string) bool {
mac := hmac.New(sha256.New, []byte(secret))
if _, err := mac.Write([]byte(r.APIKey)); err != nil {
panic(err)
}
return hmac.Equal([]byte(r.Token), []byte(hex.EncodeToString(mac.Sum(nil))))
}
type OffersRequest struct {
OffersFilter `url:"filter,omitempty"`
}

483
v5/response.go Normal file
View file

@ -0,0 +1,483 @@
package v5
// SuccessfulResponse type
type SuccessfulResponse struct {
Success bool `json:"success,omitempty"`
}
// CreateResponse type
type CreateResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
}
// OperationResponse type
type OperationResponse struct {
Success bool `json:"success"`
Errors map[string]string `json:"errors,omitempty,brackets"`
}
// VersionResponse return available API versions
type VersionResponse struct {
Success bool `json:"success,omitempty"`
Versions []string `json:"versions,brackets,omitempty"`
}
// CredentialResponse return available API methods
type CredentialResponse struct {
Success bool `json:"success,omitempty"`
Credentials []string `json:"credentials,brackets,omitempty"`
SiteAccess string `json:"siteAccess,omitempty"`
SitesAvailable []string `json:"sitesAvailable,brackets,omitempty"`
}
// CustomerResponse type
type CustomerResponse struct {
Success bool `json:"success"`
Customer *Customer `json:"customer,omitempty,brackets"`
}
// CorporateCustomerResponse type
type CorporateCustomerResponse struct {
Success bool `json:"success"`
CorporateCustomer *CorporateCustomer `json:"customerCorporate,omitempty,brackets"`
}
// CustomersResponse type
type CustomersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Customers []Customer `json:"customers,omitempty,brackets"`
}
// CorporateCustomersResponse type
type CorporateCustomersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomersCorporate []CorporateCustomer `json:"customersCorporate,omitempty,brackets"`
}
// CorporateCustomersNotesResponse type
type CorporateCustomersNotesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Notes []Note `json:"notes,omitempty,brackets"`
}
// CorporateCustomersAddressesResponse type
type CorporateCustomersAddressesResponse struct {
Success bool `json:"success"`
Addresses []CorporateCustomerAddress `json:"addresses"`
}
// CorporateCustomerCompaniesResponse type
type CorporateCustomerCompaniesResponse struct {
Success bool `json:"success"`
Companies []Company `json:"companies"`
}
// CorporateCustomerContactsResponse type
type CorporateCustomerContactsResponse struct {
Success bool `json:"success"`
Contacts []CorporateCustomerContact `json:"contacts"`
}
// CustomerChangeResponse type
type CustomerChangeResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
State string `json:"state,omitempty"`
}
// CorporateCustomerChangeResponse type
type CorporateCustomerChangeResponse CustomerChangeResponse
// CustomersUploadResponse type
type CustomersUploadResponse struct {
Success bool `json:"success"`
UploadedCustomers []IdentifiersPair `json:"uploadedCustomers,omitempty,brackets"`
}
// CorporateCustomersUploadResponse type
type CorporateCustomersUploadResponse CustomersUploadResponse
// CustomersHistoryResponse type
type CustomersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []CustomerHistoryRecord `json:"history,omitempty,brackets"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// CorporateCustomersHistoryResponse type
type CorporateCustomersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []CorporateCustomerHistoryRecord `json:"history,omitempty,brackets"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// OrderResponse type
type OrderResponse struct {
Success bool `json:"success"`
Order *Order `json:"order,omitempty,brackets"`
}
// OrdersResponse type
type OrdersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Orders []Order `json:"orders,omitempty,brackets"`
}
// OrdersStatusesResponse type
type OrdersStatusesResponse struct {
Success bool `json:"success"`
Orders []OrdersStatus `json:"orders"`
}
// OrdersUploadResponse type
type OrdersUploadResponse struct {
Success bool `json:"success"`
UploadedOrders []IdentifiersPair `json:"uploadedOrders,omitempty,brackets"`
}
// OrdersHistoryResponse type
type OrdersHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []OrdersHistoryRecord `json:"history,omitempty,brackets"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// PackResponse type
type PackResponse struct {
Success bool `json:"success"`
Pack *Pack `json:"pack,omitempty,brackets"`
}
// PacksResponse type
type PacksResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Packs []Pack `json:"packs,omitempty,brackets"`
}
// PacksHistoryResponse type
type PacksHistoryResponse struct {
Success bool `json:"success,omitempty"`
GeneratedAt string `json:"generatedAt,omitempty"`
History []PacksHistoryRecord `json:"history,omitempty,brackets"`
Pagination *Pagination `json:"pagination,omitempty"`
}
// UserResponse type
type UserResponse struct {
Success bool `json:"success"`
User *User `json:"user,omitempty,brackets"`
}
// UsersResponse type
type UsersResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Users []User `json:"users,omitempty,brackets"`
}
// UserGroupsResponse type
type UserGroupsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Groups []UserGroup `json:"groups,omitempty,brackets"`
}
// TaskResponse type
type TaskResponse struct {
Success bool `json:"success"`
Task *Task `json:"task,omitempty,brackets"`
}
// TasksResponse type
type TasksResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Tasks []Task `json:"tasks,omitempty,brackets"`
}
// NotesResponse type
type NotesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Notes []Note `json:"notes,omitempty,brackets"`
}
// SegmentsResponse type
type SegmentsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Segments []Segment `json:"segments,omitempty,brackets"`
}
// CountriesResponse type
type CountriesResponse struct {
Success bool `json:"success"`
CountriesIso []string `json:"countriesIso,omitempty,brackets"`
}
// CostGroupsResponse type
type CostGroupsResponse struct {
Success bool `json:"success"`
CostGroups []CostGroup `json:"costGroups,omitempty,brackets"`
}
// CostItemsResponse type
type CostItemsResponse struct {
Success bool `json:"success"`
CostItems []CostItem `json:"costItems,omitempty,brackets"`
}
// CouriersResponse type
type CouriersResponse struct {
Success bool `json:"success"`
Couriers []Courier `json:"couriers,omitempty,brackets"`
}
// DeliveryServiceResponse type
type DeliveryServiceResponse struct {
Success bool `json:"success"`
DeliveryServices map[string]DeliveryService `json:"deliveryServices,omitempty,brackets"`
}
// DeliveryTypesResponse type
type DeliveryTypesResponse struct {
Success bool `json:"success"`
DeliveryTypes map[string]DeliveryType `json:"deliveryTypes,omitempty,brackets"`
}
// LegalEntitiesResponse type
type LegalEntitiesResponse struct {
Success bool `json:"success"`
LegalEntities []LegalEntity `json:"legalEntities,omitempty,brackets"`
}
// OrderMethodsResponse type
type OrderMethodsResponse struct {
Success bool `json:"success"`
OrderMethods map[string]OrderMethod `json:"orderMethods,omitempty,brackets"`
}
// OrderTypesResponse type
type OrderTypesResponse struct {
Success bool `json:"success"`
OrderTypes map[string]OrderType `json:"orderTypes,omitempty,brackets"`
}
// PaymentStatusesResponse type
type PaymentStatusesResponse struct {
Success bool `json:"success"`
PaymentStatuses map[string]PaymentStatus `json:"paymentStatuses,omitempty,brackets"`
}
// PaymentTypesResponse type
type PaymentTypesResponse struct {
Success bool `json:"success"`
PaymentTypes map[string]PaymentType `json:"paymentTypes,omitempty,brackets"`
}
// PriceTypesResponse type
type PriceTypesResponse struct {
Success bool `json:"success"`
PriceTypes []PriceType `json:"priceTypes,omitempty,brackets"`
}
// ProductStatusesResponse type
type ProductStatusesResponse struct {
Success bool `json:"success"`
ProductStatuses map[string]ProductStatus `json:"productStatuses,omitempty,brackets"`
}
// StatusesResponse type
type StatusesResponse struct {
Success bool `json:"success"`
Statuses map[string]Status `json:"statuses,omitempty,brackets"`
}
// StatusGroupsResponse type
type StatusGroupsResponse struct {
Success bool `json:"success"`
StatusGroups map[string]StatusGroup `json:"statusGroups,omitempty,brackets"`
}
// SitesResponse type
type SitesResponse struct {
Success bool `json:"success"`
Sites map[string]Site `json:"sites,omitempty,brackets"`
}
// StoresResponse type
type StoresResponse struct {
Success bool `json:"success"`
Stores []Store `json:"stores,omitempty,brackets"`
}
// InventoriesResponse type
type InventoriesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Offers []Offer `json:"offers,omitempty"`
}
// StoreUploadResponse type
type StoreUploadResponse struct {
Success bool `json:"success"`
ProcessedOffersCount int `json:"processedOffersCount,omitempty"`
NotFoundOffers []Offer `json:"notFoundOffers,omitempty"`
}
// ProductsGroupsResponse type
type ProductsGroupsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
ProductGroup []ProductGroup `json:"productGroup,omitempty,brackets"`
}
// ProductsResponse type
type ProductsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Products []Product `json:"products,omitempty,brackets"`
}
// ProductsPropertiesResponse type
type ProductsPropertiesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Properties []Property `json:"properties,omitempty,brackets"`
}
// DeliveryShipmentsResponse type
type DeliveryShipmentsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
DeliveryShipments []DeliveryShipment `json:"deliveryShipments,omitempty,brackets"`
}
// DeliveryShipmentResponse type
type DeliveryShipmentResponse struct {
Success bool `json:"success"`
DeliveryShipment *DeliveryShipment `json:"deliveryShipment,omitempty,brackets"`
}
// DeliveryShipmentUpdateResponse type
type DeliveryShipmentUpdateResponse struct {
Success bool `json:"success"`
ID int `json:"id,omitempty"`
Status string `json:"status,omitempty"`
}
// IntegrationModuleResponse type
type IntegrationModuleResponse struct {
Success bool `json:"success"`
IntegrationModule *IntegrationModule `json:"integrationModule,omitempty"`
}
// IntegrationModuleEditResponse type
type IntegrationModuleEditResponse struct {
Success bool `json:"success"`
Info ResponseInfo `json:"info,omitempty,brackets"`
}
// ResponseInfo type
type ResponseInfo struct {
MgTransportInfo MgInfo `json:"mgTransport,omitempty,brackets"`
MgBotInfo MgInfo `json:"mgBot,omitempty,brackets"`
}
// MgInfo type
type MgInfo struct {
EndpointUrl string `json:"endpointUrl"`
Token string `json:"token"`
}
// CostsResponse type
type CostsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Costs []Cost `json:"costs,omitempty,brackets"`
}
// CostsUploadResponse type
type CostsUploadResponse struct {
Success bool `json:"success"`
UploadedCosts []int `json:"uploadedCosts,omitempty,brackets"`
}
// CostsDeleteResponse type
type CostsDeleteResponse struct {
Success bool `json:"success"`
Count int `json:"count,omitempty,brackets"`
NotRemovedIds []int `json:"notRemovedIds,omitempty,brackets"`
}
// CostResponse type
type CostResponse struct {
Success bool `json:"success"`
Cost *Cost `json:"cost,omitempty,brackets"`
}
// FilesResponse type
type FilesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
Files []File `json:"files,omitempty"`
}
// FileUpload response
type FileUploadResponse struct {
Success bool `json:"success"`
File *File `json:"file,omitempty"`
}
// FileResponse type
type FileResponse struct {
Success bool `json:"success"`
File *File `json:"file,omitempty"`
}
// CustomFieldsResponse type
type CustomFieldsResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomFields []CustomFields `json:"customFields,omitempty,brackets"`
}
// CustomDictionariesResponse type
type CustomDictionariesResponse struct {
Success bool `json:"success"`
Pagination *Pagination `json:"pagination,omitempty"`
CustomDictionaries *[]CustomDictionary `json:"customDictionaries,omitempty,brackets"`
}
// CustomResponse type
type CustomResponse struct {
Success bool `json:"success"`
Code string `json:"code,omitempty"`
}
// CustomDictionaryResponse type
type CustomDictionaryResponse struct {
Success bool `json:"success"`
CustomDictionary *CustomDictionary `json:"CustomDictionary,omitempty,brackets"`
}
// CustomFieldResponse type
type CustomFieldResponse struct {
Success bool `json:"success"`
CustomField CustomFields `json:"customField,omitempty,brackets"`
}
// UnitsResponse type
type UnitsResponse struct {
Success bool `json:"success"`
Units *[]Unit `json:"units,omitempty,brackets"`
}

1086
v5/types.go Normal file

File diff suppressed because it is too large Load diff