From 5c6d2ebead217f5916767a9a542117fa496c677b Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 5 Sep 2023 15:06:08 +0300 Subject: [PATCH 1/3] Adding functionality from recent updates to the library --- client.go | 298 +++++++++++++++++++++++++++++++++++ client_test.go | 418 +++++++++++++++++++++++++++++++++++++++++++++++++ filters.go | 5 +- response.go | 28 ++++ types.go | 68 +++++++- 5 files changed, 808 insertions(+), 9 deletions(-) diff --git a/client.go b/client.go index 6fe5207..804b8b1 100644 --- a/client.go +++ b/client.go @@ -2109,6 +2109,304 @@ func (c *Client) IntegrationModule(code string) (IntegrationModuleResponse, int, return resp, status, nil } +// LinksCreate creates a link +// +// For more information see https://www.simla.com/docs/Developers/API/APIVersions/APIv5#post--api-v5-orders-links-create +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.LinksCreate(retailcrm.SerializedOrderLink{ +// Comment: "comment for link", +// Orders: []retailcrm.LinkedOrder{{ID: 10}, {ID: 12}}, +// }) +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// +// if data.Success == true { +// log.Println("Creating a link") +// } +func (c *Client) LinksCreate(link SerializedOrderLink, site ...string) (SuccessfulResponse, int, error) { + var resp SuccessfulResponse + + linkJson, _ := json.Marshal(link) + + p := url.Values{ + "link": {string(linkJson)}, + } + + fillSite(&p, site) + + data, status, err := c.PostRequest("/orders/links/create", p) + + if err != nil { + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + +// ClientIdsUpload uploading of web analytics clientId +// +// For more information see https://docs.simla.com/Developers/API/APIVersions/APIv5#post--api-v5-web-analytics-client-ids-upload +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.ClientIdsUpload([]retailcrm.ClientId{ +// { +// Value: "value", +// Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, +// Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalID"}, +// Site: "site", +// }, +// { +// Value: "value", +// Order: LinkedOrder{ID: 12, ExternalID: "externalID2", Number: "number2"}, +// Customer: SerializedEntityCustomer{ID: 12, ExternalID: "externalID2"}, +// Site: "site2", +// }, +// }) +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// +// if data.Success == true { +// log.Println("Upload is successful") +// } +func (c *Client) ClientIdsUpload(clientIds []ClientId) (ClientIdResponse, int, error) { + var resp ClientIdResponse + clientIdsJSON, _ := json.Marshal(&clientIds) + + p := url.Values{ + "clientIds": {string(clientIdsJSON)}, + } + + data, status, err := c.PostRequest("/web-analytics/client-ids/upload", p) + if err != nil { + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + +// SourcesUpload uploading of sources +// +// For more information see https://docs.simla.com/Developers/API/APIVersions/APIv5#post--api-v5-web-analytics-sources-upload +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.SourcesUpload([]retailcrm.Source{ +// { +// Source: "source", +// Medium: "medium", +// Campaign: "campaign", +// Keyword: "keyword", +// Content: "content", +// ClientId: "10", +// Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, +// Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, +// Site: "site", +// }, +// }) +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// +// if data.Success == true { +// log.Println("Upload is successful!") +// } +func (c *Client) SourcesUpload(sources []Source) (SourcesResponse, int, error) { + var resp SourcesResponse + sourcesJSON, _ := json.Marshal(&sources) + + p := url.Values{ + "sources": {string(sourcesJSON)}, + } + + data, status, err := c.PostRequest("/web-analytics/sources/upload", p) + if err != nil { + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + +// Currencies returns a list of currencies +// +// For more information see https://docs.simla.com/Developers/API/APIVersions/APIv5#get--api-v5-reference-currencies +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.Currencies() +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// +// for _, value := range data.Currencies { +// log.Printf("%v\n", value) +// } +func (c *Client) Currencies() (CurrencyResponse, int, error) { + var resp CurrencyResponse + + data, status, err := c.GetRequest("/reference/currencies") + if err != nil { + + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + +// CurrenciesCreate create currency +// +// For more information see https://docs.simla.com/Developers/API/APIVersions/APIv5#post--api-v5-reference-currencies-create +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.CurrenciesCreate(retailcrm.Currency{ +// Code: "RUB", +// IsBase: true, +// IsAutoConvert: true, +// AutoConvertExtraPercent: 1, +// ManualConvertNominal: 1, +// ManualConvertValue: 1, +// }) +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// +// if data.Success == true { +// log.Println("Create currency") +// } +func (c *Client) CurrenciesCreate(currency Currency) (CurrencyCreateResponse, int, error) { + var resp CurrencyCreateResponse + currencyJSON, _ := json.Marshal(¤cy) + + p := url.Values{ + "currency": {string(currencyJSON)}, + } + + data, status, err := c.PostRequest("/reference/currencies/create", p) + if err != nil { + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + +// CurrenciesEdit edit an currency +// +// For more information see https://docs.simla.com/Developers/API/APIVersions/APIv5#post--api-v5-reference-currencies-id-edit +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// data, status, err := client.CurrenciesEdit( +// retailcrm.Currency{ +// ID: 10, +// Code: "RUB", +// IsBase: true, +// IsAutoConvert: true, +// AutoConvertExtraPercent: 1, +// ManualConvertNominal: 1, +// ManualConvertValue: 1, +// }, +// ) +// +// if err != nil { +// if apiErr, ok := retailcrm.AsAPIError(err); ok { +// log.Fatalf("http status: %d, %s", status, apiErr.String()) +// } +// +// log.Fatalf("http status: %d, error: %s", status, err) +// } +// if data.Success == true { +// log.Println("Currency was edit") +// } +func (c *Client) CurrenciesEdit(currency Currency) (SuccessfulResponse, int, error) { + var resp SuccessfulResponse + var uid = strconv.Itoa(currency.ID) + + currencyJSON, _ := json.Marshal(¤cy) + + p := url.Values{ + "currency": {string(currencyJSON)}, + } + + data, status, err := c.PostRequest(fmt.Sprintf("/reference/currencies/%s/edit", uid), p) + if err != nil { + return resp, status, err + } + + err = json.Unmarshal(data, &resp) + if err != nil { + return resp, status, err + } + + return resp, status, nil +} + // IntegrationModuleEdit integration module create/edit // // For more information see http://www.simla.com/docs/Developers/API/APIVersions/APIv5#get--api-v5-integration-modules-code diff --git a/client_test.go b/client_test.go index 94b84c1..6691785 100644 --- a/client_test.go +++ b/client_test.go @@ -1988,6 +1988,424 @@ func TestClient_OrdersOrders_Fail(t *testing.T) { } } +func TestClient_LinksCreate(t *testing.T) { + c := client() + + orders := []LinkedOrder{{ID: 10}, {ID: 12}} + + link := SerializedOrderLink{ + Comment: "comment", + Orders: orders, + } + + linkJson, _ := json.Marshal(link) + + p := url.Values{ + "link": {string(linkJson)}, + } + + defer gock.Off() + + gock.New(crmURL). + Post("/links/create"). + BodyString(p.Encode()). + Reply(201). + BodyString(`{"success": true}`) + + data, status, err := c.LinksCreate(link) + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } +} + +func TestClient_ClientIdsUpload(t *testing.T) { + c := client() + + clientIds := []ClientId{ + { + Value: "value", + Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, + Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalID"}, + Site: "site", + }, + { + Value: "value2", + Order: LinkedOrder{ID: 12, ExternalID: "externalID2", Number: "number2"}, + Customer: SerializedEntityCustomer{ID: 12, ExternalID: "externalID2"}, + Site: "site2", + }, + } + + clientIdsJSON, _ := json.Marshal(&clientIds) + + p := url.Values{ + "clientIds": {string(clientIdsJSON)}, + } + + defer gock.Off() + gock.New(crmURL). + Post("/web-analytics/client-ids/upload"). + BodyString(p.Encode()). + Reply(201). + BodyString(`{"success": true}`) + + data, status, err := c.ClientIdsUpload(clientIds) + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } +} + +func TestClient_ClientIdsUpload_Fail(t *testing.T) { + c := client() + + clientIds := []ClientId{ + { + Value: "value", + Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, + Customer: SerializedEntityCustomer{}, + Site: "site", + }, + { + Value: "value2", + Order: LinkedOrder{ID: 12, ExternalID: "externalID2", Number: "number2"}, + Customer: SerializedEntityCustomer{ID: 12, ExternalID: "externalID2"}, + Site: "site2", + }, + } + + clientIdsJSON, _ := json.Marshal(&clientIds) + + p := url.Values{ + "clientIds": {string(clientIdsJSON)}, + } + + defer gock.Off() + gock.New(crmURL). + Post("/web-analytics/client-ids/upload"). + BodyString(p.Encode()). + Reply(460). + BodyString(` + { + "success": false, + "failedClientIds": { + "value": "value", + "order": { + "id": 10, + "externalID": "externalID", + "number": "number" + }, + "customer": {}. + "site": "site2" + }, + "errorMsg": "customer is required", + "errors": [460] + } + `) + + data, _, err := c.ClientIdsUpload(clientIds) + + if err == nil { + t.Error("Error must be return") + } + + if data.Success != false { + t.Error(successFail) + } +} + +func TestClient_SourcesUpload(t *testing.T) { + c := client() + + sources := []Source{ + { + Source: "source", + Medium: "medium", + Campaign: "campaign", + Keyword: "keyword", + Content: "content", + ClientId: "10", + Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, + Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, + Site: "site", + }, + } + + sourcesJSON, _ := json.Marshal(&sources) + + p := url.Values{ + "sources": {string(sourcesJSON)}, + } + + defer gock.Off() + gock.New(crmURL). + Post("/web-analytics/sources/upload"). + BodyString(p.Encode()). + Reply(201). + BodyString(`{"success": true}`) + + data, status, err := c.SourcesUpload(sources) + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } +} + +func TestClient_SourcesUpload_Fail(t *testing.T) { + c := client() + + sources := []Source{ + { + Source: "source", + Medium: "medium", + Campaign: "campaign", + Keyword: "keyword", + Content: "content", + ClientId: "10", + Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, + Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, + Site: "site", + }, + { + Source: "source", + Medium: "medium", + Campaign: "campaign", + Keyword: "keyword", + Content: "content", + ClientId: "12", + Order: LinkedOrder{}, + Customer: SerializedEntityCustomer{}, + Site: "site", + }, + } + + sourcesJSON, _ := json.Marshal(&sources) + + p := url.Values{ + "sources": {string(sourcesJSON)}, + } + + gock.New(crmURL). + Post("/web-analytics/sources/upload"). + BodyString(p.Encode()). + Reply(460). + BodyString(` + { + "success": false, + "failedSources": { + "source": "source", + "medium": "medium", + "campaign": "campaign", + "keyword": "keyword", + "content": "content", + "order": {}, + "customer": {}. + "site": "sitey" + }, + "errorMsg": "order and customer is required", + "errors": [460] + } + `) + + data, _, err := c.SourcesUpload(sources) + + if err == nil { + t.Error("Error must be return") + } + + if data.Success != false { + t.Error(successFail) + } +} + +func TestClient_Currencies(t *testing.T) { + c := client() + + defer gock.Off() + gock.New(crmURL). + Get("/reference/currencies"). + Reply(200). + BodyString(` + { + "success": true, + "currencies": [ + { + "id": 10, + "code": "code", + "isBase": true, + "isAutoConvert": true, + "autoConvertExtraPercent": 1, + "manualConvertNominal": 1, + "manualConvertValue": 1.5 + }, + { + "id": 12, + "code": "code2", + "isBase": false, + "isAutoConvert": false, + "autoConvertExtra_percent": 2, + "manualConvertNominal": 5, + "manualConvertValue": 60.25 + } + ] + }`) + + resp := CurrencyResponse{ + Success: true, + Currencies: []Currency{ + { + ID: 10, + Code: "code", + IsBase: true, + IsAutoConvert: true, + AutoConvertExtraPercent: 1, + ManualConvertNominal: 1, + ManualConvertValue: 1.5, + }, + { + ID: 12, + Code: "code2", + IsBase: false, + IsAutoConvert: false, + AutoConvertExtraPercent: 0, + ManualConvertNominal: 5, + ManualConvertValue: 60.25, + }, + }, + } + + data, status, err := c.Currencies() + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } + + assert.Equal(t, resp, data) +} + +func TestClient_CurrenciesCreate(t *testing.T) { + c := client() + + currency := Currency{ + ID: 10, + Code: "code", + IsBase: true, + IsAutoConvert: true, + AutoConvertExtraPercent: 1, + ManualConvertNominal: 1, + ManualConvertValue: 1.5, + } + + currencyJSON, _ := json.Marshal(¤cy) + + p := url.Values{ + "currency": {string(currencyJSON)}, + } + + defer gock.Off() + gock.New(crmURL). + Post("/reference/currencies/create"). + BodyString(p.Encode()). + Reply(201). + BodyString(`{"success": true, "id": 10}`) + + data, status, err := c.CurrenciesCreate(currency) + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } + + assert.Equal(t, currency.ID, data.ID) +} + +func TestClient_CurrenciesEdit(t *testing.T) { + c := client() + + currency := Currency{ + ID: 10, + Code: "code", + IsBase: true, + IsAutoConvert: true, + AutoConvertExtraPercent: 1, + ManualConvertNominal: 1, + ManualConvertValue: 1.5, + } + var uid = strconv.Itoa(currency.ID) + currencyJSON, _ := json.Marshal(¤cy) + + p := url.Values{ + "currency": {string(currencyJSON)}, + } + + defer gock.Off() + gock.New(crmURL). + Post(fmt.Sprintf("/reference/currencies/%s/edit", uid)). + BodyString(p.Encode()). + Reply(200). + BodyString(`{"success": true}`) + + data, status, err := c.CurrenciesEdit(currency) + + if err != nil { + t.Errorf("%v", err) + } + + if status >= http.StatusBadRequest { + t.Errorf("%v", err) + } + + if data.Success != true { + + t.Errorf("%v", err) + } +} + func TestClient_OrderChange(t *testing.T) { c := client() diff --git a/filters.go b/filters.go index 762ae4f..103ba8b 100644 --- a/filters.go +++ b/filters.go @@ -199,6 +199,7 @@ type OrdersFilter struct { PaymentStatuses []string `url:"paymentStatuses,omitempty,brackets"` PaymentTypes []string `url:"paymentTypes,omitempty,brackets"` DeliveryTypes []string `url:"deliveryTypes,omitempty,brackets"` + DeliveryServices []string `url:"deliveryServices,omitempty,brackets"` OrderMethods []string `url:"orderMethods,omitempty,brackets"` ShipmentStores []string `url:"shipmentStores,omitempty,brackets"` Couriers []string `url:"couriers,omitempty,brackets"` @@ -448,8 +449,8 @@ type LoyaltyAccountAPIFilter struct { ID string `url:"id,omitempty"` Status string `url:"status,,omitempty"` Customer string `url:"customer,omitempty"` - MinOrderSum string `url:"minOrderSum,omitempty"` - MaxOrderSum string `url:"maxOrderSum,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"` diff --git a/response.go b/response.go index 36c620e..e9c538b 100644 --- a/response.go +++ b/response.go @@ -596,6 +596,34 @@ type AccountBonusOperationsResponse struct { BonusOperations []BonusOperation `json:"bonusOperations,omitempty"` } +// ClientIdResponse type +type ClientIdResponse struct { + Success bool `json:"success"` + FailedClientIds []ClientId `json:"failed_client_ids,omitempty"` + ErrorMsg string `json:"errorMsg,omitempty"` + Errors map[string]string `json:"errors,omitempty"` +} + +// SourcesResponse type +type SourcesResponse struct { + Success bool `json:"success"` + FailedSources []Source `json:"failed_sources,omitempty"` + ErrorMsg string `json:"errorMsg,omitempty"` + Errors map[string]string `json:"errors,omitempty"` +} + +//CurrencyResponse type +type CurrencyResponse struct { + Success bool `json:"success"` + Currencies []Currency `json:"currencies,omitempty"` +} + +//CurrencyCreateResponse type +type CurrencyCreateResponse struct { + Success bool `json:"success"` + ID int `json:"id,omitempty"` +} + type LoyaltyAccountResponse struct { SuccessfulResponse LoyaltyAccount `json:"loyaltyAccount"` diff --git a/types.go b/types.go index eae1ef1..36d5ae7 100644 --- a/types.go +++ b/types.go @@ -64,11 +64,15 @@ type GeoHierarchyRow struct { // Source type. type Source struct { - Source string `json:"source,omitempty"` - Medium string `json:"medium,omitempty"` - Campaign string `json:"campaign,omitempty"` - Keyword string `json:"keyword,omitempty"` - Content string `json:"content,omitempty"` + Source string `json:"source,omitempty"` + Medium string `json:"medium,omitempty"` + Campaign string `json:"campaign,omitempty"` + Keyword string `json:"keyword,omitempty"` + Content string `json:"content,omitempty"` + ClientId string `json:"client_id,omitempty"` + Order LinkedOrder `json:"order,omitempty"` + Customer SerializedEntityCustomer `json:"customer,omitempty"` + Site string `json:"site,omitempty"` } // Contragent type. @@ -344,6 +348,49 @@ type Order struct { ApplyRound *bool `json:"applyRound,omitempty"` PrivilegeType string `json:"privilegeType,omitempty"` DialogID int `json:"dialogId,omitempty"` + Links []OrderLink `json:"links,omitempty"` + Currency string `json:"currency,omitempty"` +} + +// LinkedOrder type +type LinkedOrder struct { + ID int `json:"id,omitempty"` + Number string `json:"number,omitempty"` + ExternalID string `json:"externalID,omitempty"` +} + +// OrderLink type +type OrderLink struct { + Comment string `json:"comment,omitempty"` + Order LinkedOrder `json:"order,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` +} + +// SerializedOrderLink type +type SerializedOrderLink struct { + Comment string `json:"comment,omitempty"` + Orders []LinkedOrder `json:"orders,omitempty"` + CreatedAt string `json:"createdAt,omitempty"` +} + +// ClientId type +type ClientId struct { + Value string `json:"value"` + CreateAt string `json:"createAt,omitempty"` + Order LinkedOrder `json:"order,omitempty"` + Customer SerializedEntityCustomer `json:"customer,omitempty"` + Site string `json:"site,omitempty"` +} + +// Currency type +type Currency struct { + ID int `json:"id,omitempty"` + Code string `json:"code,omitempty"` + IsBase bool `json:"isBase,omitempty"` + IsAutoConvert bool `json:"isAutoConvert,omitempty"` + AutoConvertExtraPercent int `json:"autoConvertExtraPercent,omitempty"` + ManualConvertNominal int `json:"manualConvertNominal,omitempty"` + ManualConvertValue float64 `json:"manualConvertValue,omitempty"` } // OrdersStatus type. @@ -580,6 +627,7 @@ type OfferPrice struct { Price float32 `json:"price,omitempty"` Ordering int `json:"ordering,omitempty"` PriceType string `json:"priceType,omitempty"` + Currency string `json:"currency,omitempty"` } // OfferPriceUpload type. @@ -619,6 +667,7 @@ type User struct { CreatedAt string `json:"createdAt,omitempty"` Active bool `json:"active,omitempty"` Online bool `json:"online,omitempty"` + Position string `json:"position,omitempty"` IsAdmin bool `json:"isAdmin,omitempty"` IsManager bool `json:"isManager,omitempty"` Email string `json:"email,omitempty"` @@ -832,6 +881,7 @@ type DeliveryType struct { DeliveryServices []string `json:"deliveryServices,omitempty"` PaymentTypes []string `json:"paymentTypes,omitempty"` // Deprecated, use DeliveryPaymentTypes DeliveryPaymentTypes []DeliveryPaymentType `json:"deliveryPaymentTypes,omitempty"` + Currency string `json:"currency,omitempty"` } type DeliveryPaymentType struct { @@ -862,8 +912,8 @@ type LegalEntity struct { } type SerializedEntityCustomer struct { - ID int `json:"id,omitempty"` - ExternalID int `json:"externalId,omitempty"` + ID int `json:"id,omitempty"` + ExternalID string `json:"externalId,omitempty"` } // OrderMethod type. @@ -921,6 +971,7 @@ type PriceType struct { Ordering int `json:"ordering,omitempty"` Groups []string `json:"groups,omitempty"` Geo []GeoHierarchyRow `json:"geo,omitempty"` + Currency string `json:"currency,omitempty"` } // ProductStatus type. @@ -974,6 +1025,7 @@ type Site struct { IsDemo bool `json:"isDemo,omitempty"` CatalogID string `json:"catalogId,omitempty"` IsCatalogMainSite bool `json:"isCatalogMainSite,omitempty"` + Currency string `json:"currency,omitempty"` } // Store type. @@ -1381,6 +1433,7 @@ type Loyalty struct { ActivatedAt string `json:"activatedAt,omitempty"` DeactivatedAt string `json:"deactivatedAt,omitempty"` BlockedAt string `json:"blockedAt,omitempty"` + Currency string `json:"currency,omitempty"` } // LoyaltyLevel type. @@ -1424,6 +1477,7 @@ type SerializedLoyaltyOrder struct { Delivery Delivery `json:"delivery,omitempty"` Site string `json:"site,omitempty"` Items []LoyaltyItems `json:"items,omitempty"` + Currency string `json:"currency,omitempty"` } type LoyaltyEventDiscount struct { From ab648cd06ae1de94d3f42464fd345ac641928f58 Mon Sep 17 00:00:00 2001 From: Danila Date: Tue, 5 Sep 2023 18:09:36 +0300 Subject: [PATCH 2/3] Adding functionality from recent updates to the library --- api-client-go | 1 + client.go | 40 ++++++++++++++----- client_test.go | 103 +++++++++++++++++++++++-------------------------- response.go | 10 ++--- types.go | 32 +++++++-------- 5 files changed, 101 insertions(+), 85 deletions(-) create mode 160000 api-client-go diff --git a/api-client-go b/api-client-go new file mode 160000 index 0000000..5c6d2eb --- /dev/null +++ b/api-client-go @@ -0,0 +1 @@ +Subproject commit 5c6d2ebead217f5916767a9a542117fa496c677b diff --git a/client.go b/client.go index 804b8b1..abb0b3b 100644 --- a/client.go +++ b/client.go @@ -2136,10 +2136,14 @@ func (c *Client) IntegrationModule(code string) (IntegrationModuleResponse, int, func (c *Client) LinksCreate(link SerializedOrderLink, site ...string) (SuccessfulResponse, int, error) { var resp SuccessfulResponse - linkJson, _ := json.Marshal(link) + linkJSON, err := json.Marshal(link) + + if err != nil { + return resp, http.StatusBadRequest, err + } p := url.Values{ - "link": {string(linkJson)}, + "link": {string(linkJSON)}, } fillSite(&p, site) @@ -2166,7 +2170,7 @@ func (c *Client) LinksCreate(link SerializedOrderLink, site ...string) (Successf // // var client = retailcrm.New("https://demo.url", "09jIJ") // -// data, status, err := client.ClientIdsUpload([]retailcrm.ClientId{ +// data, status, err := client.ClientIdsUpload([]retailcrm.ClientID{ // { // Value: "value", // Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, @@ -2192,9 +2196,13 @@ func (c *Client) LinksCreate(link SerializedOrderLink, site ...string) (Successf // if data.Success == true { // log.Println("Upload is successful") // } -func (c *Client) ClientIdsUpload(clientIds []ClientId) (ClientIdResponse, int, error) { - var resp ClientIdResponse - clientIdsJSON, _ := json.Marshal(&clientIds) +func (c *Client) ClientIdsUpload(clientIds []ClientID) (ClientIDResponse, int, error) { + var resp ClientIDResponse + clientIdsJSON, err := json.Marshal(&clientIds) + + if err != nil { + return resp, http.StatusBadRequest, err + } p := url.Values{ "clientIds": {string(clientIdsJSON)}, @@ -2228,7 +2236,7 @@ func (c *Client) ClientIdsUpload(clientIds []ClientId) (ClientIdResponse, int, e // Campaign: "campaign", // Keyword: "keyword", // Content: "content", -// ClientId: "10", +// ClientID: "10", // Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, // Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, // Site: "site", @@ -2248,7 +2256,11 @@ func (c *Client) ClientIdsUpload(clientIds []ClientId) (ClientIdResponse, int, e // } func (c *Client) SourcesUpload(sources []Source) (SourcesResponse, int, error) { var resp SourcesResponse - sourcesJSON, _ := json.Marshal(&sources) + sourcesJSON, err := json.Marshal(&sources) + + if err != nil { + return resp, http.StatusBadRequest, err + } p := url.Values{ "sources": {string(sourcesJSON)}, @@ -2335,7 +2347,11 @@ func (c *Client) Currencies() (CurrencyResponse, int, error) { // } func (c *Client) CurrenciesCreate(currency Currency) (CurrencyCreateResponse, int, error) { var resp CurrencyCreateResponse - currencyJSON, _ := json.Marshal(¤cy) + currencyJSON, err := json.Marshal(¤cy) + + if err != nil { + return resp, http.StatusBadRequest, err + } p := url.Values{ "currency": {string(currencyJSON)}, @@ -2388,7 +2404,11 @@ func (c *Client) CurrenciesEdit(currency Currency) (SuccessfulResponse, int, err var resp SuccessfulResponse var uid = strconv.Itoa(currency.ID) - currencyJSON, _ := json.Marshal(¤cy) + currencyJSON, err := json.Marshal(¤cy) + + if err != nil { + return resp, http.StatusBadRequest, err + } p := url.Values{ "currency": {string(currencyJSON)}, diff --git a/client_test.go b/client_test.go index 6691785..ce64aa6 100644 --- a/client_test.go +++ b/client_test.go @@ -1998,10 +1998,10 @@ func TestClient_LinksCreate(t *testing.T) { Orders: orders, } - linkJson, _ := json.Marshal(link) + linkJSON, _ := json.Marshal(link) p := url.Values{ - "link": {string(linkJson)}, + "link": {string(linkJSON)}, } defer gock.Off() @@ -2028,10 +2028,45 @@ func TestClient_LinksCreate(t *testing.T) { } } +func TestClient_LinksCreate_Fail(t *testing.T) { + c := client() + + orders := []LinkedOrder{{ID: 10}} + + link := SerializedOrderLink{ + Comment: "comment", + Orders: orders, + } + + linkJSON, _ := json.Marshal(link) + + p := url.Values{ + "link": {string(linkJSON)}, + } + + defer gock.Off() + + gock.New(crmURL). + Post("/links/create"). + BodyString(p.Encode()). + Reply(400). + BodyString(`{"errorMsg": "Errors in the entity format", errors: [orders: "This collection should contain 2 elements or more."}`) + + data, _, err := c.LinksCreate(link) + + if err == nil { + t.Error("Error must be return") + } + + if data.Success != false { + t.Error(successFail) + } +} + func TestClient_ClientIdsUpload(t *testing.T) { c := client() - clientIds := []ClientId{ + clientIds := []ClientID{ { Value: "value", Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, @@ -2078,18 +2113,11 @@ func TestClient_ClientIdsUpload(t *testing.T) { func TestClient_ClientIdsUpload_Fail(t *testing.T) { c := client() - clientIds := []ClientId{ + clientIds := []ClientID{ { Value: "value", - Order: LinkedOrder{ID: 10, ExternalID: "externalID", Number: "number"}, + Order: LinkedOrder{ID: 10}, Customer: SerializedEntityCustomer{}, - Site: "site", - }, - { - Value: "value2", - Order: LinkedOrder{ID: 12, ExternalID: "externalID2", Number: "number2"}, - Customer: SerializedEntityCustomer{ID: 12, ExternalID: "externalID2"}, - Site: "site2", }, } @@ -2103,22 +2131,11 @@ func TestClient_ClientIdsUpload_Fail(t *testing.T) { gock.New(crmURL). Post("/web-analytics/client-ids/upload"). BodyString(p.Encode()). - Reply(460). + Reply(400). BodyString(` { - "success": false, - "failedClientIds": { - "value": "value", - "order": { - "id": 10, - "externalID": "externalID", - "number": "number" - }, - "customer": {}. - "site": "site2" - }, - "errorMsg": "customer is required", - "errors": [460] + "errorMsg": "ClientIds are loaded with errors", + "errors": [0: "customer: Set one of the following fields: id, externalId"] } `) @@ -2143,7 +2160,7 @@ func TestClient_SourcesUpload(t *testing.T) { Campaign: "campaign", Keyword: "keyword", Content: "content", - ClientId: "10", + ClientID: "10", Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, Site: "site", @@ -2189,19 +2206,8 @@ func TestClient_SourcesUpload_Fail(t *testing.T) { Campaign: "campaign", Keyword: "keyword", Content: "content", - ClientId: "10", + ClientID: "12", Order: LinkedOrder{ID: 10, ExternalID: "externalId", Number: "number"}, - Customer: SerializedEntityCustomer{ID: 10, ExternalID: "externalId"}, - Site: "site", - }, - { - Source: "source", - Medium: "medium", - Campaign: "campaign", - Keyword: "keyword", - Content: "content", - ClientId: "12", - Order: LinkedOrder{}, Customer: SerializedEntityCustomer{}, Site: "site", }, @@ -2216,22 +2222,11 @@ func TestClient_SourcesUpload_Fail(t *testing.T) { gock.New(crmURL). Post("/web-analytics/sources/upload"). BodyString(p.Encode()). - Reply(460). + Reply(400). BodyString(` { - "success": false, - "failedSources": { - "source": "source", - "medium": "medium", - "campaign": "campaign", - "keyword": "keyword", - "content": "content", - "order": {}, - "customer": {}. - "site": "sitey" - }, - "errorMsg": "order and customer is required", - "errors": [460] + "errorMsg": "ClientIds are loaded with errors", + "errors": [0: "customer: Set one of the following fields: id, externalId"] } `) @@ -2325,7 +2320,7 @@ func TestClient_CurrenciesCreate(t *testing.T) { currency := Currency{ ID: 10, - Code: "code", + Code: "RUB", IsBase: true, IsAutoConvert: true, AutoConvertExtraPercent: 1, diff --git a/response.go b/response.go index e9c538b..78e3e65 100644 --- a/response.go +++ b/response.go @@ -596,18 +596,18 @@ type AccountBonusOperationsResponse struct { BonusOperations []BonusOperation `json:"bonusOperations,omitempty"` } -// ClientIdResponse type -type ClientIdResponse struct { - Success bool `json:"success"` - FailedClientIds []ClientId `json:"failed_client_ids,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 { Success bool `json:"success"` - FailedSources []Source `json:"failed_sources,omitempty"` + FailedSources []Source `json:"failedSources,omitempty"` ErrorMsg string `json:"errorMsg,omitempty"` Errors map[string]string `json:"errors,omitempty"` } diff --git a/types.go b/types.go index 36d5ae7..e0ae080 100644 --- a/types.go +++ b/types.go @@ -69,7 +69,7 @@ type Source struct { Campaign string `json:"campaign,omitempty"` Keyword string `json:"keyword,omitempty"` Content string `json:"content,omitempty"` - ClientId string `json:"client_id,omitempty"` + ClientID string `json:"client_id,omitempty"` Order LinkedOrder `json:"order,omitempty"` Customer SerializedEntityCustomer `json:"customer,omitempty"` Site string `json:"site,omitempty"` @@ -352,45 +352,45 @@ type Order struct { Currency string `json:"currency,omitempty"` } -// LinkedOrder type +// LinkedOrder type. type LinkedOrder struct { - ID int `json:"id,omitempty"` Number string `json:"number,omitempty"` ExternalID string `json:"externalID,omitempty"` + ID int `json:"id,omitempty"` } -// OrderLink type +// OrderLink type. type OrderLink struct { Comment string `json:"comment,omitempty"` - Order LinkedOrder `json:"order,omitempty"` CreatedAt string `json:"createdAt,omitempty"` + Order LinkedOrder `json:"order,omitempty"` } -// SerializedOrderLink type +// SerializedOrderLink type. type SerializedOrderLink struct { Comment string `json:"comment,omitempty"` - Orders []LinkedOrder `json:"orders,omitempty"` CreatedAt string `json:"createdAt,omitempty"` + Orders []LinkedOrder `json:"orders,omitempty"` } -// ClientId type -type ClientId struct { +// ClientID type. +type ClientID struct { Value string `json:"value"` CreateAt string `json:"createAt,omitempty"` - Order LinkedOrder `json:"order,omitempty"` - Customer SerializedEntityCustomer `json:"customer,omitempty"` Site string `json:"site,omitempty"` + Customer SerializedEntityCustomer `json:"customer,omitempty"` + Order LinkedOrder `json:"order,omitempty"` } -// Currency type +// Currency type. type Currency struct { - ID int `json:"id,omitempty"` Code string `json:"code,omitempty"` + ID int `json:"id,omitempty"` + ManualConvertNominal int `json:"manualConvertNominal,omitempty"` + AutoConvertExtraPercent int `json:"autoConvertExtraPercent,omitempty"` IsBase bool `json:"isBase,omitempty"` IsAutoConvert bool `json:"isAutoConvert,omitempty"` - AutoConvertExtraPercent int `json:"autoConvertExtraPercent,omitempty"` - ManualConvertNominal int `json:"manualConvertNominal,omitempty"` - ManualConvertValue float64 `json:"manualConvertValue,omitempty"` + ManualConvertValue float32 `json:"manualConvertValue,omitempty"` } // OrdersStatus type. From 583362bfe3e1366823b1a92b7508c5e28d9cca63 Mon Sep 17 00:00:00 2001 From: Danila Date: Wed, 6 Sep 2023 07:40:46 +0300 Subject: [PATCH 3/3] Adding functionality from recent updates to the library --- client.go | 1 - response.go | 12 ++++++------ types.go | 2 +- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/client.go b/client.go index abb0b3b..6c0cdc8 100644 --- a/client.go +++ b/client.go @@ -2305,7 +2305,6 @@ func (c *Client) Currencies() (CurrencyResponse, int, error) { data, status, err := c.GetRequest("/reference/currencies") if err != nil { - return resp, status, err } diff --git a/response.go b/response.go index 78e3e65..748f4da 100644 --- a/response.go +++ b/response.go @@ -604,21 +604,21 @@ type ClientIDResponse struct { Success bool `json:"success"` } -// SourcesResponse type +// SourcesResponse type. type SourcesResponse struct { - Success bool `json:"success"` - FailedSources []Source `json:"failedSources,omitempty"` ErrorMsg string `json:"errorMsg,omitempty"` Errors map[string]string `json:"errors,omitempty"` + FailedSources []Source `json:"failed_sources,omitempty"` + Success bool `json:"success"` } -//CurrencyResponse type +// CurrencyResponse type. type CurrencyResponse struct { - Success bool `json:"success"` Currencies []Currency `json:"currencies,omitempty"` + Success bool `json:"success"` } -//CurrencyCreateResponse type +// CurrencyCreateResponse type. type CurrencyCreateResponse struct { Success bool `json:"success"` ID int `json:"id,omitempty"` diff --git a/types.go b/types.go index e0ae080..6e72ebf 100644 --- a/types.go +++ b/types.go @@ -70,9 +70,9 @@ type Source struct { Keyword string `json:"keyword,omitempty"` Content string `json:"content,omitempty"` ClientID string `json:"client_id,omitempty"` + Site string `json:"site,omitempty"` Order LinkedOrder `json:"order,omitempty"` Customer SerializedEntityCustomer `json:"customer,omitempty"` - Site string `json:"site,omitempty"` } // Contragent type.