From a4e90a79d709ceaa6e810a9cf9271fff4562ea2e Mon Sep 17 00:00:00 2001 From: Pavel Date: Sat, 8 Jun 2024 14:40:47 +0300 Subject: [PATCH] add custom encoder (need testing with amo) and delete double logic for save status deals, for future connect to tg trashlog --- internal/models/createDeal.go | 57 ++++++++++++++++++- internal/repository/redis_repo.go | 10 ++++ internal/tools/construct.go | 4 +- .../workers/post_deals_worker/deals_worker.go | 17 +++--- .../post_fields_worker/fields_worker.go | 3 +- pkg/amoClient/amo.go | 15 +++-- tests/json/json_test.go | 52 +++++++++++++++++ 7 files changed, 135 insertions(+), 23 deletions(-) create mode 100644 tests/json/json_test.go diff --git a/internal/models/createDeal.go b/internal/models/createDeal.go index 0792d8e..0721649 100644 --- a/internal/models/createDeal.go +++ b/internal/models/createDeal.go @@ -1,5 +1,10 @@ package models +import ( + "encoding/json" + "fmt" +) + type DealReq struct { Name string `json:"name"` // название сделки Price int `json:"price"` // бюджет сделки @@ -18,9 +23,11 @@ type DealReq struct { RequestID string `json:"request_id"` } +type ValueInterface interface{} + type FieldsValues struct { - FieldID int `json:"field_id"` - Values []interface{} `json:"values"` + FieldID int `json:"field_id"` + Values []ValueInterface `json:"values"` } type Values struct { @@ -37,6 +44,52 @@ type ValueFile struct { FileSize int64 `json:"file_size"` } +func (fv *FieldsValues) UnmarshalJSON(data []byte) error { + type Alias FieldsValues + aux := struct { + Alias + FieldID int `json:"field_id"` + Values []json.RawMessage `json:"values"` + }{} + + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + fv.FieldID = aux.FieldID + fv.Values = make([]ValueInterface, len(aux.Values)) + + for i, rawVal := range aux.Values { + var v map[string]interface{} + if err := json.Unmarshal(rawVal, &v); err != nil { + return err + } + + if _, ok := v["value"]; !ok { + return fmt.Errorf("missing value in JSON") + } + + var value ValueInterface + if _, ok := v["value"].(map[string]interface{}); ok { + var fileStruct ValuesFile + if err := json.Unmarshal(rawVal, &fileStruct); err != nil { + return err + } + value = fileStruct + } else { + var valValue Values + if err := json.Unmarshal(rawVal, &valValue); err != nil { + return err + } + value = valValue + } + + fv.Values[i] = value + } + + return nil +} + type Embedd struct { Tags []Tag `json:"tags"` // Данные тегов, добавляемых к сделке Contact []Contact `json:"contacts"` // Данные контактов, которые будет прикреплены к сделке diff --git a/internal/repository/redis_repo.go b/internal/repository/redis_repo.go index 1e82e81..025118c 100644 --- a/internal/repository/redis_repo.go +++ b/internal/repository/redis_repo.go @@ -4,6 +4,7 @@ import ( "amocrm/internal/models" "context" "encoding/json" + "fmt" "github.com/go-redis/redis/v8" "go.uber.org/zap" "strconv" @@ -49,6 +50,7 @@ func (r *Repository) CachingLeadFieldsToRedis(ctx context.Context, answerID int6 return err } + fmt.Println(string(leadFieldsJson), "CHECK CACHING LEAD FIELDS") err = r.redisClient.Set(ctx, key, leadFieldsJson, 0).Err() if err != nil { return err @@ -104,6 +106,14 @@ func (r *Repository) FetchingDeals(ctx context.Context) (map[string][]models.Map return } + fmt.Println("CUSTOM ENCODER", leadFields) + + for _, f := range leadFields { + fmt.Println(f.FieldID) + fmt.Println(f.Values[0]) + fmt.Println(f.Values[1]) + } + mu.Lock() defer mu.Unlock() diff --git a/internal/tools/construct.go b/internal/tools/construct.go index e00312b..30e9485 100644 --- a/internal/tools/construct.go +++ b/internal/tools/construct.go @@ -114,7 +114,7 @@ func EmojiUnicode(text string) string { func AddContactFields(contactFields []models.FieldsValues, fieldValue string, fieldType model.ContactQuizConfig, fieldMap map[string]int) []models.FieldsValues { if fieldValue != "" { - values := make([]interface{}, 0) + values := make([]models.ValueInterface, 0) values = append(values, models.Values{Value: fieldValue}) contactFields = append(contactFields, models.FieldsValues{ @@ -129,7 +129,7 @@ func ConstructUTMFields(utmMap model.UTMSavingMap, currentFields []model.Field) var fields []models.FieldsValues for _, field := range currentFields { if data, ok := utmMap[field.Name]; ok { - val := []interface{}{ + val := []models.ValueInterface{ models.Values{ Value: data, }, diff --git a/internal/workers/post_deals_worker/deals_worker.go b/internal/workers/post_deals_worker/deals_worker.go index e257845..1002b84 100644 --- a/internal/workers/post_deals_worker/deals_worker.go +++ b/internal/workers/post_deals_worker/deals_worker.go @@ -142,9 +142,11 @@ func (wc *PostDeals) sendingDealsReq(ctx context.Context, mapDealReq map[string] for accessToken, deal := range mapDealReq { resp, err := wc.amoClient.CreatingDeal(deal, accessToken) if err != nil { + // todo логирование в тг wc.logger.Error("error creating deal in amo", zap.Error(err)) + return err } - err = wc.saveDealToDB(ctx, resp, accessToken, err) + err = wc.saveDealToDB(ctx, resp, accessToken) if err != nil { wc.logger.Error("error saving resp data to db", zap.Error(err)) return err @@ -153,11 +155,8 @@ func (wc *PostDeals) sendingDealsReq(ctx context.Context, mapDealReq map[string] return nil } -func (wc *PostDeals) saveDealToDB(ctx context.Context, resp []models.DealResp, accessToken string, errResp error) error { +func (wc *PostDeals) saveDealToDB(ctx context.Context, resp []models.DealResp, accessToken string) error { status := "pending" - if errResp != nil { - status = errResp.Error() - } for _, dealResp := range resp { requestID := strings.Join(dealResp.RequestID, ",") answerID, err := strconv.ParseInt(requestID, 10, 64) @@ -189,10 +188,10 @@ func (wc *PostDeals) saveDealToDB(ctx context.Context, resp []models.DealResp, a func (wc *PostDeals) constructField(ctx context.Context, 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][]interface{}) - entityFieldsMap[model.LeadsType] = make(map[int][]interface{}) - entityFieldsMap[model.CompaniesType] = make(map[int][]interface{}) - entityFieldsMap[model.CustomersType] = make(map[int][]interface{}) + entityFieldsMap := make(map[model.EntityType]map[int][]models.ValueInterface) + entityFieldsMap[model.LeadsType] = make(map[int][]models.ValueInterface) + entityFieldsMap[model.CompaniesType] = make(map[int][]models.ValueInterface) + entityFieldsMap[model.CustomersType] = make(map[int][]models.ValueInterface) entityRules := make(map[model.EntityType][]model.FieldRule) entityRules[model.LeadsType] = result.FieldsRule.Lead diff --git a/internal/workers/post_fields_worker/fields_worker.go b/internal/workers/post_fields_worker/fields_worker.go index 7bd4cb0..45fd33e 100644 --- a/internal/workers/post_fields_worker/fields_worker.go +++ b/internal/workers/post_fields_worker/fields_worker.go @@ -91,6 +91,7 @@ func (wc *PostFields) sendForUpdate(ctx context.Context, token string, dealsData resp, errResp := wc.amoClient.UpdatingDeal(reqToUpdate, token) if errResp != nil { + // todo также логирование ошибки в тг wc.logger.Error("error sendig request for update deal fields", zap.Error(errResp)) for _, data := range reqToUpdate { errorCheckerMap[data.DealID] = struct{}{} @@ -101,7 +102,6 @@ func (wc *PostFields) sendForUpdate(ctx context.Context, token string, dealsData err := wc.updateDealStatus(ctx, DealStatus{ Resp: resp, AccessToken: token, - ErrResp: errResp, }) if err != nil { @@ -115,7 +115,6 @@ func (wc *PostFields) sendForUpdate(ctx context.Context, token string, dealsData type DealStatus struct { Resp *models.UpdateDealResp AccessToken string - ErrResp error } func (wc *PostFields) updateDealStatus(ctx context.Context, deps DealStatus) error { diff --git a/pkg/amoClient/amo.go b/pkg/amoClient/amo.go index 48d7806..1594b8b 100644 --- a/pkg/amoClient/amo.go +++ b/pkg/amoClient/amo.go @@ -440,14 +440,6 @@ func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string) ([]models.D agent.Set("Authorization", "Bearer "+accessToken) statusCode, resBody, errs := agent.Bytes() - - 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 - } - if len(errs) > 0 { for _, err = range errs { a.logger.Error("error sending request in Creating Deal for creating deals", zap.Error(err)) @@ -461,6 +453,13 @@ func (a *Amo) CreatingDeal(req []models.DealReq, accessToken string) ([]models.D return nil, fmt.Errorf(errorMessage) } + 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 } time.Sleep(a.rateLimiter.Interval) diff --git a/tests/json/json_test.go b/tests/json/json_test.go new file mode 100644 index 0000000..677cdd1 --- /dev/null +++ b/tests/json/json_test.go @@ -0,0 +1,52 @@ +package json + +import ( + "amocrm/internal/models" + "encoding/json" + "fmt" + "github.com/stretchr/testify/assert" + "testing" +) + +func TestUnmarshalJSON(t *testing.T) { + jsonData := []byte(`[ + { + "field_id": 1, + "values": [ + {"value": "Value1"}, + {"value": {"file_uuid": "123e4567file_uuid", "version_uuid": "123e4567version_uuid", "file_name": "file.pdf", "file_size": 1}} + ] + }, + { + "field_id": 2, + "values": [ + {"value": "Value2"}, + {"value": {"file_uuid": "98765432file_uuid", "version_uuid": "98765432version_uuid", "file_name": "file.wc", "file_size": 2}} + ] + }, + { + "field_id": 3, + "values": [ + {"value": "Value3"}, + {"value": {"file_uuid": "abcdeffile_uuid", "version_uuid": "abcdefversion_uuid", "file_name": "file.txt", "file_size": 3}} + ] + } +] +`) + + var fv []models.FieldsValues + err := json.Unmarshal(jsonData, &fv) + if err != nil { + t.Errorf("UnmarshalJSON failed: %v", err) + } + + for _, f := range fv { + fmt.Println(f) + } + assert.Equal(t, 3, len(fv)) + + jsonAgain, err := json.Marshal(fv) + assert.NoError(t, err) + + fmt.Println(string(jsonAgain)) +}