refactor logic for posting deals

This commit is contained in:
Pavel 2024-05-05 15:22:54 +03:00
parent f21dadfd01
commit 02263b0ed0
9 changed files with 95 additions and 97 deletions

2
go.mod

@ -12,7 +12,7 @@ require (
github.com/twmb/franz-go v1.16.1
go.uber.org/zap v1.27.0
google.golang.org/protobuf v1.33.0
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240504123552-f1d3073dc9f1
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240505074742-07895eccdd07
penahub.gitlab.yandexcloud.net/backend/quiz/core.git v0.0.0-20240219174804-d78fd38511af
)

4
go.sum

@ -151,7 +151,7 @@ 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-20240504123552-f1d3073dc9f1 h1:H+2MgBImU5ab8vIFLQCUw0Az85BHKNXi2yPqKtX8sR0=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240504123552-f1d3073dc9f1/go.mod h1:oRyhT55ctjqp/7ZxIzkR7OsQ7T/NLibsfrbb7Ytns64=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240505074742-07895eccdd07 h1:ttTQdCfoOj5L/C6xv9GEVDd23LWGkvgZCCEXvSXzjEo=
penahub.gitlab.yandexcloud.net/backend/quiz/common.git v0.0.0-20240505074742-07895eccdd07/go.mod h1:oRyhT55ctjqp/7ZxIzkR7OsQ7T/NLibsfrbb7Ytns64=
penahub.gitlab.yandexcloud.net/backend/quiz/core.git v0.0.0-20240219174804-d78fd38511af h1:jQ7HaXSutDX5iepU7VRImxhikK7lV/lBKkiloOZ4Emo=
penahub.gitlab.yandexcloud.net/backend/quiz/core.git v0.0.0-20240219174804-d78fd38511af/go.mod h1:5S5YwjSXWmnEKjBjG6MtyGtFmljjukDRS8CwHk/CF/I=

@ -29,7 +29,7 @@ func (c *Controller) UpdateListCustom(ctx *fiber.Ctx) error {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
//accountID := "64f2cd7a7047f28fdabf6d9e"
//accountID := "654a8909725f47e926f0bebc"
err := c.service.UpdateListCustom(ctx.Context(), accountID)
if err != nil {

@ -12,7 +12,7 @@ func (c *Controller) UpdateListUsers(ctx *fiber.Ctx) error {
return ctx.Status(fiber.StatusUnauthorized).SendString("account id is required")
}
//accountID := "64f2cd7a7047f28fdabf6d9e"
//accountID := "654a8909725f47e926f0bebc"
err := c.service.UpdateListUsers(ctx.Context(), accountID)

@ -15,6 +15,7 @@ type DealReq struct {
CustomFieldsValues []FieldsValues `json:"custom_fields_values"` // Массив полей которые заполняются значениями
TagsToAdd []Tag `json:"tags_to_add"` // Массив тегов для добавления
Embed Embedd `json:"_embedded"`
RequestID string `json:"request_id"`
}
type FieldsValues struct {
@ -34,17 +35,24 @@ type Embedd struct {
}
type Contact struct {
//ID int32 `json:"id"` // ID контакта
//IsMain bool `json:"is_main"` // Флаг, показывающий, является контакт главным или нет
//ID int32 `json:"id"` // ID контакта
IsMain bool `json:"is_main"` // Флаг, показывающий, является контакт главным или нет
Name string `json:"first_name"`
CreatedAT int64 `json:"created_at"`
CreatedAt int64 `json:"created_at"`
UpdatedBy int `json:"updated_by"`
ResponsibleUserID int32 `json:"responsible_user_id"` // ID пользователя, ответственного за сделку, в нашем случае PerformerID
CustomFieldsValues []FieldsValues `json:"custom_fields_values"` // Массив полей которые заполняются значениями
}
type Company struct {
ID int `json:"id"` // ID компании
//ID int32 `json:"id"` // ID компании
Name string `json:"name"` // Название компании
ResponsibleUserID int32 `json:"responsible_user_id"` // ID пользователя, ответственного за сделку, в нашем случае PerformerID
CreatedBy int32 `json:"created_by"` // id пользователя amoid который создает сделку (тот кто подключил интеграцию)
UpdatedBy int `json:"updated_by"`
CreatedAt int64 `json:"created_at"`
UpdatedAt int64 `json:"updated_at"` // Дата изменения сделки, передается в Unix Timestamp
CustomFieldsValues []FieldsValues `json:"custom_fields_values"` // Массив полей которые заполняются значениями
}
type Source struct {
@ -53,16 +61,9 @@ type Source struct {
}
type DealResp struct {
Link struct {
SelfLink `json:"self"`
} `json:"_links"`
Embed struct {
Leads []struct {
ID int `json:"id"`
RequestID string `json:"request_id"`
Links struct {
SelfLink `json:"self"`
} `json:"_links"`
}
} `json:"_embedded"`
DealID int `json:"id"` // ID сделки
ContactID int `json:"contact_id"` // ID контакта
CompanyID int `json:"company_id"` // ID компании
Merged bool `json:"merged"` // Флаг, который показывает, найден дубль подходящий под условия поиска дублей и произведено объединение или нет
RequestID []string `json:"request_id"` // Массив строк с пользовательскими идентификаторами, которые были переданы с каждой сущностью
}

@ -3,6 +3,7 @@ package tools
import (
"amocrm/internal/models"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/model"
"time"
)
func ToPipeline(amoPipelines []models.Pipeline) []model.Pipeline {
@ -64,66 +65,72 @@ func ToField(amoField []models.CustomField, entity model.EntityType) []model.Fie
return fields
}
func ConstructField(allAnswers []model.ResultAnswer, fieldsRule model.Fieldsrule) []models.FieldsValues {
fieldsMap := make(map[int][]models.Values)
// todo Для добавляемых сущностей (сделка, контакт, компания), можно передать не более 40 значений дополнительных полей.
func ConstructField(allAnswers []model.ResultAnswer, result model.AmoUsersTrueResults) ([]models.FieldsValues, []models.Contact, []models.Company) {
entityFieldsMap := make(map[model.EntityType]map[int][]models.Values)
entityFieldsMap[model.LeadsType] = make(map[int][]models.Values)
entityFieldsMap[model.ContactsType] = make(map[int][]models.Values)
entityFieldsMap[model.CompaniesType] = make(map[int][]models.Values)
entityFieldsMap[model.CustomersType] = make(map[int][]models.Values)
if fieldsRule.Lead != nil {
for _, rule := range fieldsRule.Lead {
entityRules := make(map[model.EntityType][]model.FieldRule)
entityRules[model.LeadsType] = result.FieldsRule.Lead
entityRules[model.ContactsType] = result.FieldsRule.Contact
entityRules[model.CompaniesType] = result.FieldsRule.Company
entityRules[model.CustomersType] = result.FieldsRule.Customer
for entityType, ruleList := range entityRules {
for _, rule := range ruleList {
for _, data := range allAnswers {
if fieldID, ok := rule.Questionid[int(data.QuestionID)]; ok {
values := fieldsMap[fieldID]
values := entityFieldsMap[entityType][fieldID]
values = append(values, models.Values{Value: data.Content})
fieldsMap[fieldID] = values
entityFieldsMap[entityType][fieldID] = values
}
}
}
}
if fieldsRule.Contact != nil {
for _, rule := range fieldsRule.Contact {
for _, data := range allAnswers {
if fieldID, ok := rule.Questionid[int(data.QuestionID)]; ok {
values := fieldsMap[fieldID]
values = append(values, models.Values{Value: data.Content})
fieldsMap[fieldID] = values
}
var leadFields []models.FieldsValues
var contactFields []models.FieldsValues
var companyFields []models.FieldsValues
var customerFields []models.FieldsValues
for entityType, fieldMap := range entityFieldsMap {
for fieldID, values := range fieldMap {
field := models.FieldsValues{
FieldID: fieldID,
Values: values,
}
switch entityType {
case model.LeadsType:
leadFields = append(leadFields, field)
case model.ContactsType:
contactFields = append(contactFields, field)
case model.CompaniesType:
companyFields = append(companyFields, field)
case model.CustomersType:
customerFields = append(customerFields, field)
}
}
}
if fieldsRule.Company != nil {
for _, rule := range fieldsRule.Company {
for _, data := range allAnswers {
if fieldID, ok := rule.Questionid[int(data.QuestionID)]; ok {
values := fieldsMap[fieldID]
values = append(values, models.Values{Value: data.Content})
fieldsMap[fieldID] = values
}
}
return leadFields, []models.Contact{
{
Name: result.PerformerName,
CreatedAt: time.Now().Unix(),
UpdatedBy: 0,
ResponsibleUserID: result.PerformerID,
CustomFieldsValues: contactFields,
},
}, []models.Company{
{
Name: "OOO PENA CO",
ResponsibleUserID: result.PerformerID,
CreatedBy: 0,
UpdatedBy: 0,
CreatedAt: time.Now().Unix(),
CustomFieldsValues: companyFields,
},
}
}
if fieldsRule.Customer != nil {
for _, rule := range fieldsRule.Customer {
for _, data := range allAnswers {
if fieldID, ok := rule.Questionid[int(data.QuestionID)]; ok {
values := fieldsMap[fieldID]
values = append(values, models.Values{Value: data.Content})
fieldsMap[fieldID] = values
}
}
}
}
var fields []models.FieldsValues
for fieldID, values := range fieldsMap {
field := models.FieldsValues{
FieldID: fieldID,
Values: values,
}
fields = append(fields, field)
}
return fields
}

@ -51,7 +51,7 @@ func ToCreatedUpdateQuestionRules(questionsTypeMap map[model.EntityType][]model.
for _, question := range questions {
matched := false
for _, field := range currentFields {
if question.Title == field.Name {
if question.Title == field.Name && entity == field.Entity {
toUpdate[int(question.Id)] = int(field.Amoid)
matched = true
break

@ -8,6 +8,7 @@ import (
"fmt"
"go.uber.org/zap"
"penahub.gitlab.yandexcloud.net/backend/quiz/common.git/dal"
"strconv"
"time"
)
@ -32,7 +33,7 @@ func NewPostFieldsWC(deps Deps) *PostFields {
}
func (wc *PostFields) Start(ctx context.Context) {
ticker := time.NewTicker(10 * time.Second)
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for {
@ -61,41 +62,30 @@ func (wc *PostFields) startFetching(ctx context.Context) {
wc.logger.Error("error getting all user answers by result session", zap.Error(err))
return
}
//todo За один запрос можно передать не более 50 сделок.
deal := models.DealReq{
Name: fmt.Sprintf("deal quiz number %d", result.QuizID),
StatusID: 48703678, //result.StepID,
PipelineID: 5505076, //result.PipelineID,
CreatedBy: 0, //result.AmoAccountID,
StatusID: result.StepID,
PipelineID: result.PipelineID,
CreatedBy: 0, //result.AmoAccountID,
UpdatedBy: 0,
CreatedAt: time.Now().Unix(),
ResponsibleUserID: result.PerformerID,
Embed: models.Embedd{
Contact: []models.Contact{
{
Name: "Дмитрий",
CreatedAT: time.Now().Unix(),
UpdatedBy: 0,
ResponsibleUserID: result.PerformerID,
CustomFieldsValues: []models.FieldsValues{
{
FieldID: 1153687,
Values: []models.Values{
{
Value: "Saint_Petersburg",
},
},
},
},
},
},
Company: []models.Company{},
Source: models.Source{
Type: "widget",
},
},
// строка которая будет возвращенна в респонсе чтоб понимать кто есть что
RequestID: strconv.Itoa(int(result.AnswerID)),
}
fields := tools.ConstructField(allAnswers, result.FieldsRule)
deal.CustomFieldsValues = fields
leadFields, contactData, companyData := tools.ConstructField(allAnswers, result)
deal.CustomFieldsValues = leadFields
deal.Embed.Contact = contactData
deal.Embed.Company = companyData
mapDealReq[result.AccessToken] = append(mapDealReq[result.AccessToken], deal)
}

@ -428,7 +428,7 @@ func (a *Amo) AddFields(req []models.AddLeadsFields, entity model.EntityType, ac
}
}
func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string) (*models.DealResp, error) {
func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string) ([]models.DealResp, error) {
for {
if a.rateLimiter.Check() {
uri := fmt.Sprintf("%s/api/v4/leads/complex", a.baseApiURL)
@ -456,14 +456,14 @@ func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string) (*models.De
return nil, fmt.Errorf(errorMessage)
}
var resp models.DealResp
var resp []models.DealResp
err = json.Unmarshal(resBody, &resp)
if err != nil {
a.logger.Error("error unmarshal response body in Creating Deal:", zap.Error(err))
return nil, err
}
return &resp, nil
return resp, nil
}
time.Sleep(a.rateLimiter.Interval)
}