add client for creating customers in amo

This commit is contained in:
Pavel 2024-05-08 12:33:03 +03:00
parent 7a2e8c3a0b
commit 439677ca3c
6 changed files with 105 additions and 31 deletions

4
go.sum

@ -169,10 +169,6 @@ gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
penahub.gitlab.yandexcloud.net/backend/penahub_common v0.0.0-20240223054633-6cb3d5ce45b6 h1:oV+/HNX+JPoQ3/GUx08hio7d45WpY0AMGrFs7j70QlA=
penahub.gitlab.yandexcloud.net/backend/penahub_common v0.0.0-20240223054633-6cb3d5ce45b6/go.mod h1:lTmpjry+8evVkXWbEC+WMOELcFkRD1lFMc7J09mOndM=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507152904-b2e6000c1f40 h1:2/7GQGyMcwISIXVj0bapGEy2FDHrI9FskMSqc6peGjM=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507152904-b2e6000c1f40/go.mod h1:oRyhT55ctjqp/7ZxIzkR7OsQ7T/NLibsfrbb7Ytns64=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507173031-17e2f6acba38 h1:50i28g5lzVthJHS5r+3sPrmRBlfNag8lngN+CkdrbN0=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507173031-17e2f6acba38/go.mod h1:oRyhT55ctjqp/7ZxIzkR7OsQ7T/NLibsfrbb7Ytns64=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507175756-10399fe4c21f h1:xUo4CsauxNgFhiTfv+5BKfF4Ekk6SHeR+ohwrBuJIrU=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240507175756-10399fe4c21f/go.mod h1:oRyhT55ctjqp/7ZxIzkR7OsQ7T/NLibsfrbb7Ytns64=
penahub.gitlab.yandexcloud.net/backend/quiz/core.git v0.0.0-20240219174804-d78fd38511af h1:jQ7HaXSutDX5iepU7VRImxhikK7lV/lBKkiloOZ4Emo=

@ -25,7 +25,7 @@ func (c *Controller) ChangeQuizSettings(ctx *fiber.Ctx) error {
return ctx.Status(fiber.StatusBadRequest).SendString("failed convert quizID to int")
}
//accountID := "64f2cd7a7047f28fdabf6d9e"
//accountID := "654a8909725f47e926f0bebc"
var request model.RulesReq
if err := ctx.BodyParser(&request); err != nil {

@ -35,8 +35,6 @@ type Embedd struct {
}
type Contact struct {
//ID int32 `json:"id"` // ID контакта
//IsMain bool `json:"is_main"` // Флаг, показывающий, является контакт главным или нет
Name string `json:"first_name"`
ResponsibleUserID int32 `json:"responsible_user_id"` // ID пользователя, ответственного за сделку, в нашем случае PerformerID
CreatedBy int32 `json:"created_by"` // id пользователя amoid который создает сделку (тот кто подключил интеграцию)
@ -47,7 +45,6 @@ type Contact struct {
}
type Company struct {
//ID int32 `json:"id"` // ID компании
Name string `json:"name"` // Название компании
ResponsibleUserID int32 `json:"responsible_user_id"` // ID пользователя, ответственного за сделку, в нашем случае PerformerID
CreatedBy int32 `json:"created_by"` // id пользователя amoid который создает сделку (тот кто подключил интеграцию)
@ -85,3 +82,31 @@ type EmbeddedUpdateDeal struct {
UpdatedAt int64 `json:"updated_at"`
}
}
type Customer struct {
Name string `json:"name"`
NextPrice int `json:"next_price"`
NextDate int64 `json:"next_date"`
ResponsibleUserID int32 `json:"responsible_user_id"`
StatusID *int32 `json:"status_id,omitempty"`
Periodicity int `json:"periodicity"`
CreatedBy int `json:"created_by"`
UpdatedBy int `json:"updated_by"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"`
CustomFields []FieldsValues `json:"custom_fields_values"`
TagsToAdd []Tag `json:"tags_to_add"`
Embed Embedd `json:"_embedded"`
RequestID string `json:"request_id"`
}
type CustomerResp struct {
Embedded EmbeddedCreateCustomers `json:"_embedded"`
}
type EmbeddedCreateCustomers struct {
Customers []struct {
ID int32 `json:"id"`
RequestID string `json:"request_id"`
}
}

@ -69,8 +69,9 @@ func ToField(amoField []models.CustomField, entity model.EntityType) []model.Fie
return fields
}
// todo Для добавляемых сущностей (сделка, контакт, компания), можно передать не более 40 значений дополнительных полей.
func ConstructField(allAnswers []model.ResultAnswer, result model.AmoUsersTrueResults) ([]models.FieldsValues, []models.Contact, []models.Company, error) {
func ConstructField(allAnswers []model.ResultAnswer, result model.AmoUsersTrueResults) ([]models.FieldsValues, []models.Contact, []models.Company, []models.Customer, error) {
dateCreating := time.Now().Unix()
entityFieldsMap := make(map[model.EntityType]map[int][]models.Values)
entityFieldsMap[model.LeadsType] = make(map[int][]models.Values)
entityFieldsMap[model.CompaniesType] = make(map[int][]models.Values)
@ -118,7 +119,12 @@ func ConstructField(allAnswers []model.ResultAnswer, result model.AmoUsersTrueRe
var resultInfo model.ResultContent
err := json.Unmarshal([]byte(result.Content), &resultInfo)
if err != nil {
return nil, nil, nil, err
return nil, nil, nil, nil, err
}
name := resultInfo.Name
if name == "" {
name = fmt.Sprintf("empty name, quiz %d, triggered by answer - %d", result.QuizID, result.AnswerID)
}
contactRuleMap := result.FieldsRule.Contact.ContactRuleMap
@ -131,22 +137,34 @@ func ConstructField(allAnswers []model.ResultAnswer, result model.AmoUsersTrueRe
return leadFields, []models.Contact{
{
Name: resultInfo.Name,
Name: name,
ResponsibleUserID: result.PerformerID,
CreatedBy: 0,
UpdatedBy: 0,
CreatedAt: time.Now().Unix(),
CreatedAt: dateCreating,
CustomFieldsValues: contactFields,
},
}, []models.Company{
{
Name: "OOO PENA CO",
Name: fmt.Sprintf("Компания %d", result.AnswerID),
ResponsibleUserID: result.PerformerID,
CreatedBy: 0,
UpdatedBy: 0,
CreatedAt: time.Now().Unix(),
CreatedAt: dateCreating,
CustomFieldsValues: companyFields,
},
}, []models.Customer{
{
// в амо имя покупателя не может быть пустым, надо как то с этим жить
Name: name,
ResponsibleUserID: result.PerformerID,
//StatusID: ,
CreatedBy: 0,
UpdatedBy: 0,
CreatedAt: dateCreating,
CustomFields: customerFields,
RequestID: fmt.Sprint(result.AnswerID),
},
}, nil
}

@ -87,9 +87,15 @@ func (wc *PostDeals) startFetching(ctx context.Context) {
RequestID: strconv.Itoa(int(result.AnswerID)),
}
leadFields, contactData, companyData, err := tools.ConstructField(allAnswers, result)
leadFields, contactData, companyData, customerToCreate, err := tools.ConstructField(allAnswers, result)
if err != nil {
wc.logger.Error("error serialization resultContent to model ResultContent")
wc.logger.Error("error serialization resultContent to model ResultContent", zap.Error(err))
return
}
_, err = wc.amoClient.CreatingCustomer(customerToCreate, result.AccessToken)
if err != nil {
wc.logger.Error("error sending requests for create customer", zap.Error(err))
return
}
@ -106,7 +112,7 @@ func (wc *PostDeals) startFetching(ctx context.Context) {
wc.logger.Info("reached maximum number of deals for access token", zap.String("access_token", result.AccessToken))
err = wc.sendingDealsReq(ctx, mapDealReq)
if err != nil {
wc.logger.Error("error sending requests for create deals")
wc.logger.Error("error sending requests for create deals", zap.Error(err))
return
}
mapDealReq = make(map[string][]models.DealReq)
@ -117,7 +123,7 @@ func (wc *PostDeals) startFetching(ctx context.Context) {
err = wc.sendingDealsReq(ctx, mapDealReq)
if err != nil {
wc.logger.Error("error send requests for create deals")
wc.logger.Error("error send requests for create deals", zap.Error(err))
return
}
}

@ -144,17 +144,6 @@ func (a *Amo) CreateWebHook(req models.WebHookRequest) (*models.CreateWebHookRes
}
}
// https://www.amocrm.ru/developers/content/oauth/step-by-step#%D0%A5%D1%83%D0%BA-%D0%BE%D0%B1-%D0%BE%D1%82%D0%BA%D0%BB%D1%8E%D1%87%D0%B5%D0%BD%D0%B8%D0%B8-%D0%B8%D0%BD%D1%82%D0%B5%D0%B3%D1%80%D0%B0%D1%86%D0%B8%D0%B8
func (a *Amo) DeleteWebHook() {
for {
if a.rateLimiter.Check() {
return
}
time.Sleep(a.rateLimiter.Interval)
}
}
// https://www.amocrm.ru/developers/content/crm_platform/leads_pipelines#%D0%A1%D0%BF%D0%B8%D1%81%D0%BE%D0%BA-%D1%81%D1%82%D0%B0%D1%82%D1%83%D1%81%D0%BE%D0%B2-%D0%B2%D0%BE%D1%80%D0%BE%D0%BD%D0%BA%D0%B8-%D1%81%D0%B4%D0%B5%D0%BB%D0%BE%D0%BA
// GET /api/v4/leads/pipelines/{pipeline_id}/statuses
func (a *Amo) GetListSteps(pipelineID int, accessToken string) (*models.ResponseGetListSteps, error) {
@ -508,5 +497,45 @@ func (a *Amo) UpdatingDeal(req []models.UpdateDealReq, accessToken string) (*mod
}
time.Sleep(a.rateLimiter.Interval)
}
}
func (a *Amo) CreatingCustomer(req []models.Customer, accessToken string) (*models.CustomerResp, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("%s/api/v4/customers", a.baseApiURL)
bodyBytes, err := json.Marshal(req)
if err != nil {
a.logger.Error("error marshal req in Creating Customer:", zap.Error(err))
return nil, err
}
agent := a.fiberClient.Post(uri)
agent.Set("Content-Type", "application/json").Body(bodyBytes)
agent.Set("Authorization", "Bearer "+accessToken)
statusCode, resBody, errs := agent.Bytes()
if len(errs) > 0 {
for _, err = range errs {
a.logger.Error("error sending request in Creating Customer for creating customers", zap.Error(err))
}
return nil, fmt.Errorf("request failed: %v", errs[0])
}
if statusCode != fiber.StatusOK {
errorMessage := fmt.Sprintf("received an incorrect response from Creating Customer: %s", string(resBody))
a.logger.Error(errorMessage, zap.Int("status", statusCode))
return nil, fmt.Errorf(errorMessage)
}
var resp models.CustomerResp
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Creating Customer:", zap.Error(err))
return nil, err
}
return &resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}
}