diff --git a/client.go b/client.go index 4cea643..221ca6f 100644 --- a/client.go +++ b/client.go @@ -6030,3 +6030,57 @@ func (c *Client) LoyaltyBonusStatusDetails( return result, status, nil } + +// LoyaltyAccounts return list of participations in the loyalty program +// +// For more information see https://docs.retailcrm.ru/Developers/API/APIVersions/APIv5#get--api-v5-loyalty-accounts +// +// Example: +// +// var client = retailcrm.New("https://demo.url", "09jIJ") +// +// req := LoyaltyAccountsRequest{ +// Filter: LoyaltyAccountApiFilter{ +// Status: "activated", +// PhoneNumber: "89185556363", +// Ids: []int{14}, +// Level: 5, +// Loyalties: []int{2}, +// CustomerId: "109", +// }, +// } +// +// data, status, err := client.LoyaltyAccounts(req) +// +// 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 { +// for _, account := range data.LoyaltyAccounts { +// log.Printf("%v", account.Status) +// } +// } +func (c *Client) LoyaltyAccounts(req LoyaltyAccountsRequest) (LoyaltyAccountsResponse, int, error) { + var result LoyaltyAccountsResponse + + p, _ := query.Values(req) + + resp, status, err := c.GetRequest(fmt.Sprintf("/loyalty/accounts?%s", p.Encode())) + + if err != nil { + return result, status, err + } + + err = json.Unmarshal(resp, &result) + + if err != nil { + return result, status, err + } + + return result, status, nil +} diff --git a/client_test.go b/client_test.go index 009c015..f7a6fa6 100644 --- a/client_test.go +++ b/client_test.go @@ -7270,3 +7270,47 @@ func TestClient_LoyaltyBonusStatusDetails(t *testing.T) { assert.NotEmpty(t, res.Bonuses) assert.NotEmpty(t, res.Statistic.TotalAmount) } + +func TestClient_LoyaltyAccounts(t *testing.T) { + req := LoyaltyAccountsRequest{ + Filter: LoyaltyAccountApiFilter{ + Status: "activated", + PhoneNumber: "89185556363", + Ids: []int{14}, + Level: 5, + Loyalties: []int{2}, + CustomerId: "109", + }, + } + + gock.New(crmURL). + Get(prefix + "/loyalty/accounts"). + MatchParams(map[string]string{ + "filter[phoneNumber]": "89185556363", + "filter[status]": "activated", + "filter[level]": "5", + "filter[customerId]": "109", + }). + Reply(http.StatusOK). + JSON(getLoyaltyAccountsResponse()) + + res, status, err := client().LoyaltyAccounts(req) + + if err != nil { + t.Errorf("%v", err) + } + + if !statuses[status] { + t.Errorf("%v", err) + } + + if res.Success != true { + t.Errorf("%v", err) + } + + assert.Equal(t, req.Filter.Ids[0], res.LoyaltyAccounts[0].ID) + assert.Equal(t, req.Filter.Loyalties[0], res.LoyaltyAccounts[0].Loyalty.ID) + assert.True(t, res.LoyaltyAccounts[0].Active) + assert.Equal(t, req.Filter.PhoneNumber, res.LoyaltyAccounts[0].PhoneNumber) + assert.Equal(t, req.Filter.Status, res.LoyaltyAccounts[0].Status) +} diff --git a/request.go b/request.go index c034188..db5e7df 100644 --- a/request.go +++ b/request.go @@ -259,6 +259,18 @@ type LoyaltyBonusStatusDetailsRequest struct { Filter LoyaltyBonusApiFilterType `url:"filter,omitempty"` } +type LoyaltyAccountsRequest struct { + Limit int `url:"limit,omitempty"` + Page int `url:"limit,omitempty"` + Filter LoyaltyAccountApiFilter `url:"filter,omitempty"` +} + +type LoyaltyCalculateRequest struct { + Site string `url:"site"` + Order Order `url:"order"` + Bonuses float64 `url:"bonuses"` +} + // SystemURL returns system URL from the connection request without trailing slash. func (r ConnectRequest) SystemURL() string { if r.URL == "" { diff --git a/response.go b/response.go index e6ffb6c..f38698e 100644 --- a/response.go +++ b/response.go @@ -621,7 +621,15 @@ type LoyaltyBonusStatisticResponse struct { TotalAmount float64 `json:"totalAmount"` } -type BonusDetail struct { - Date string `json:"date"` - Amount float64 `json:"amount"` +type LoyaltyAccountsResponse struct { + SuccessfulResponse + Pagination *Pagination `json:"pagination,omitempty"` + LoyaltyAccounts []LoyaltyAccount `json:"loyaltyAccounts,omitempty"` +} + +type LoyaltyCalculateResponse struct { + SuccessfulResponse + Order SerializedLoyaltyOrder `json:"order,omitempty"` + Calculations []LoyaltyCalculation `json:"calculations,omitempty"` + Loyalty Loyalty `json:"loyalty,omitempty"` } diff --git a/testutils.go b/testutils.go index cc22c53..b64585a 100644 --- a/testutils.go +++ b/testutils.go @@ -179,3 +179,44 @@ func getBonusDetailsResponse() string { ] }` } + +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" + } + ] + }` +} diff --git a/types.go b/types.go index 68fc16c..620fc99 100644 --- a/types.go +++ b/types.go @@ -328,6 +328,7 @@ type Order struct { Items []OrderItem `json:"items,omitempty"` CustomFields StringMap `json:"customFields,omitempty"` Payments OrderPayments `json:"payments,omitempty"` + ApplyRound *bool `json:"applyRound,omitempty"` } // OrdersStatus type. @@ -1294,7 +1295,7 @@ type LoyaltyAccount struct { PhoneNumber string `json:"phoneNumber,omitempty"` CardNumber string `json:"cardNumber,omitempty"` Amount float64 `json:"amount,omitempty"` - LoyaltyLevel LoyaltyLevel `json:"level"` + LoyaltyLevel LoyaltyLevel `json:"level,omitempty"` CreatedAt string `json:"createdAt,omitempty"` ActivatedAt string `json:"activatedAt,omitempty"` ConfirmedPhoneAt string `json:"confirmedPhoneAt,omitempty"` @@ -1336,6 +1337,58 @@ type LoyaltyBonus struct { ExpiredDate string `json:"expiredDate,omitempty"` } +type BonusDetail struct { + Date string `json:"date"` + Amount float64 `json:"amount"` +} + 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:"minOrderSum,omitempty"` + MaxOrderSum string `url:"maxOrderSum,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 SerializedLoyaltyOrder struct { + BonusesCreditTotal float64 `json:"bonusesCreditTotal,omitempty"` + BonusesChargeTotal float64 `json:"bonusesChargeTotal,omitempty"` + PrivilegeType string `json:"privilegeType,omitempty"` + TotalSumm float64 `json:"totalSumm,omitempty"` + PersonalDiscountPercent float64 `json:"personalDiscountPercent,omitempty"` + LoyaltyAccount LoyaltyAccount `json:"loyaltyAccount"` + LoyaltyEventDiscount LoyaltyEventDiscount `json:"loyaltyEventDiscount,omitempty"` + Customer Customer `json:"customer"` + Delivery Delivery `json:"delivery,omitempty"` + Site string `json:"site,omitempty"` + Items []OrderItem `json:"items,omitempty"` +} + +type LoyaltyEventDiscount struct { + ID int `json:"id"` +} + +type LoyaltyItems struct { + BonusesChargeTotal float64 `json:"bonusesChargeTotal,omitempty"` + BonusesCreditTotal float64 `json:"bonusesCreditTotal,omitempty"` + ID int `json:"id,omitempty"` +}